Speedment поддерживает транзакции?
Я реализовал уровень персистентности, используя Speedment, и я хотел бы протестировать код с помощью модульных тестов с пружинной загрузкой. Я пометил свои юнит-тесты следующими аннотациями:
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
public class MovieServiceTest {
...
}
По умолчанию Spring запускает новую транзакцию, окружающую каждый метод тестирования и обратные вызовы @Before/@After, выполняя откат транзакции в конце. С Speedment, однако, это не похоже на работу.
Поддерживает ли Speedment транзакции через несколько вызовов, и если да, как мне настроить Spring для использования транзакций Speedment или как настроить Speedment для использования источника данных, предоставляемого Spring?
3 ответа
Поддержка транзакций была добавлена в Speedment 3.0.17. Тем не менее, он не интегрируется с весной @Transactional
-аннотации еще нет, поэтому вам нужно будет обернуть код, который вы хотите выполнить, в одну транзакцию, как показано здесь:
txHandler.createAndAccept(tx ->
Account sender = accounts.stream()
.filter(Account.ID.equal(1))
.findAny()
.get();
Account receiver = accounts.stream()
.filter(Account.ID.equal(2))
.findAny()
.get();
accounts.update(sender.setBalance(sender.getBalance() - 100));
accounts.update(receiver.setBalance(receiver.getBalance() + 100));
tx.commit();
}
Вполне вероятно, что вы выполняете потоковую передачу по таблице, а затем выполняете операцию обновления / удаления, пока поток еще открыт. Большая часть базы данных не может справиться с открытым ResultSet
на Connection
а затем выполните операции обновления для того же соединения.
К счастью, есть простой способ: попробуйте собрать сущности, которые вы хотели бы изменить, в промежуточном Collection
(такой как List
или же Set
), а затем использовать это Collection
выполнить нужные операции.
Этот случай описан в Руководстве пользователя Speedment здесь
txHandler.createAndAccept(
tx -> {
// Collect to a list before performing actions
List<Language> toDelete = languages.stream()
.filter(Language.LANGUAGE_ID.notEqual((short) 1))
.collect(toList());
// Do the actual actions
toDelete.forEach(languages.remover());
tx.commit();
}
);
AFAIK это не (пока) - исправление: кажется, настраивает одну транзакцию на поток / оператор.
Смотрите эту статью: https://dzone.com/articles/best-java-orm-frameworks-for-postgresql
Но это должно быть возможно реализовать с написанием специального расширения: https://github.com/speedment/speedment/wiki/Tutorial:-Writing-your-own-extensions
Редактировать:
По словам разработчика ускорения, один поток отображается на одну транзакцию: https://www.slideshare.net/Hazelcast/webinar-20150305-speedment-2