TrueSql – заново учимся ходить в базу данных. Часть 3 – транзакции и соединения

Вступление

Сегодня мы продолжим обучение прямохождению в БД. Часто можно услышать, что работа с транзакциями это сложно! Вот, например, Hibernate «сам» управляет транзакциями, сессиями, контекстом! В TrueSql нет никакой сложности в работе с транзакциями. А понятий сессий и контекста, которому нужен целый менеджер просто не существует, начнем!

Транзакции

Каждая отдельная SQL-команда по-умолчанию атомарна, но их комбинация нет. Рассмотрим хрестоматийную ситуацию с атомарностью действий над данными:

create table post (
  id      bigserial primary key,
  content varchar(4000)
);

create table tag (
  id   serial primary key,
  name varchar(100)
);

create table post_tags (
  post_id bigint references post,
  tag_id int references tag
);

Задача: создать пост и его теги. Нам надо использовать транзакцию чтобы пост не остался без тегов. Мы просто воспользуемся методом .inTransaction(cn -> {...}) на DataSourceW и запишем все команды в лямбду:

@PostMapping("...") long addPost(NewPost np) {
    return ds.inTransaction(cn -> {
        var id = cn.q(
            "insert into post values (default, ?)",
            np.text // TrueSql: спрыгнуть со Cпринг паравозика пока он не разбился
        ).asGeneratedKeys("id").fetchOne();
  
        cn.q(
            "insert into post_tags values(?)",
            unfold(np.tags, t -> new Object[]{id, t})
        ).fetchNone();
  
        return id;
    });
}

Всё элементарно! Под капотом TrueSql делает рутинную работу за вас:

  • Если вы вызываете .inTransaction() на DataSourceW, то сначала TrueSql возьмет из пула соединение.

  • После, TrueSql запомнит стратегию autoCommit из вашего Connection/DataSource.

  • На время исполнения команд в одной транзакции autoCommit выключается.

  • После выполнения ваших команд пытаемся вызвать commit () и возвращаем результат. Вызываем rollback () если лямбда завершилась с исключением.

  • Возвращаем значение autoCommit.

Еще никогда в Java не было такой простоты и прозрачности при работе с транзакциями. Бонусом упомянем, что данный запрос также можно было исполнить с помощью батчинга (будет статья) или вообще одним запросом как в truesql-petclinic-rest.

Пин соединения

В случае если вам нужно получить соединение из пула, нужно воспользоваться методом .withConnection(cn -> {...}), например:

ds.withConnection(cn -> {
  cn.q("set time zone 'America/New_York'").fetchNone();
  // ...
});

Также, такой захват соединения может вам понадобиться для временных таблиц >:(и прочих небезопасных вещей (могут съесть всю память на вашем сервере СУБД).

Лучший в мире за работой

Мы уже прошли середину пути в нашем обучении. Каждый своими глазами видит Силу.

Сайт проекта:  https://truej.net/

Наш TG-канал. Тут вы можете задавать свои вопросы, находить ответы.

Документация. Всем, кто уже настрадался с паровозиком Spring Data и его друзьями, предлагаю поставить звездочку. Может это спасет вас от кривой Фреди-Крюгера.

В следующих сериях:

  • Хранимые процедуры

  • unfold-параметры

  • Батчинг

  • Композиция TrueSql DSL

  • Ча-Ча-Ча с базой данных — advanced fetching

© Habrahabr.ru