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