Я хочу управлять своими транзакциями с помощью Spring @Transactional
и поддерживать вложенную транзакцию, следуя this example, чтобы сделать это.Весенние вложенные транзакции, не работающие с jOOQ
Моя проблема в том, если я называю UserService.addAdmin()
, что SpringTransactionProvider.begin()
и SpringTransactionProvider.commit()
не вызывался по какой-то причине, что свидетельствует о том, что он не работает так, как я делаю это ..
У меня мой service внедрено:
/*
*
*/
public class UserService {
private final static Logger LOGGER = Logger.getLogger(UserService.class.getName());
private AdminRepository adminRepository;
public UserService(DSLContext ctx) {
this.adminRepository = new AdminRepository(ctx);
}
@Transactional
public void addAdmin(String userId) {
DSLContext ctx = adminRepository.getCtx();
ctx.insertInto(Admin.ADMIN)
.set(Admin.ADMIN.USER_NAME, userId)
.execute();
}
}
Как определить мой configuration fileсервлет-context.xml
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver" />
<property name="url" value="jdbc:postgresql://localhost:5432/mz_db" />
<property name="username" value="postgres" />
<property name="password" value="huehuehue" />
</bean>
<!-- Configure Spring's transaction manager to use a DataSource -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- Configure jOOQ's TransactionProvider as a proxy to Spring's transaction manager -->
<bean id="transactionProvider"
class="com.mz.server.web.SpringTransactionProvider">
</bean>
<!-- Configure jOOQ's ConnectionProvider to use Spring's TransactionAwareDataSourceProxy,
which can dynamically discover the transaction context -->
<bean id="transactionAwareDataSource"
class="org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy">
<constructor-arg ref="dataSource" />
</bean>
<bean class="org.jooq.impl.DataSourceConnectionProvider" name="connectionProvider">
<constructor-arg ref="transactionAwareDataSource" />
</bean>
<!-- Configure the DSL object, optionally overriding jOOQ Exceptions with Spring Exceptions -->
<bean id="dsl" class="org.jooq.impl.DefaultDSLContext">
<constructor-arg ref="config" />
</bean>
<!-- Invoking an internal, package-private constructor for the example
Implement your own Configuration for more reliable behaviour -->
<bean class="org.jooq.impl.DefaultConfiguration" name="config">
<property name="SQLDialect"><value type="org.jooq.SQLDialect">POSTGRES_9_4</value></property>
<property name="connectionProvider" ref="connectionProvider" />
<property name="transactionProvider" ref="transactionProvider" />
</bean>
<!-- BEGIN Services -->
<bean id="userService" class="com.mz.server.web.service.UserService">
<constructor-arg>
<ref bean="dsl" />
</constructor-arg>
</bean>
и в основном копия SpringTransactionProvider
:
public class SpringTransactionProvider implements TransactionProvider {
private final static Logger LOGGER = Logger.getLogger(SpringTransactionProvider.class);
@Autowired
DataSourceTransactionManager txMgr;
public SpringTransactionProvider() {
LOGGER.info("Ctor()");
}
@Override
public void begin(TransactionContext ctx) {
LOGGER.info("##### begin #####");
TransactionStatus tx = txMgr.getTransaction(new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_NESTED));
ctx.transaction(new SpringTransaction(tx));
}
@Override
public void commit(TransactionContext ctx) {
LOGGER.info("##### commit #####");
txMgr.commit(((SpringTransaction) ctx.transaction()).tx);
}
@Override
public void rollback(TransactionContext ctx) {
LOGGER.info("##### rollback #####");
txMgr.rollback(((SpringTransaction) ctx.transaction()).tx);
}
}
я бы ожидал увидеть
INFO com.mz.server.web.SpringTransactionProvider - Ctor()
DEBUG com.mz.server.web.servlet.UserServletImpl - Login request by userId: username
INFO com.mz.server.web.SpringTransactionProvider - #### begin ####
INFO com.mz.server.web.service.UserService - Yay!
INFO com.mz.server.web.SpringTransactionProvider - #### commit ####
, но я только получаю
INFO com.mz.server.web.SpringTransactionProvider - Ctor()
DEBUG com.mz.server.web.servlet.UserServletImpl - Login request by userId: username
INFO com.mz.server.web.service.UserService - Yay!
Почему не получает Использовались SpringTrancationProvider
?
Ну ладно, я вижу! Причина, по которой я хотел использовать '@ Transactional', - это, например, в Hibernate с использованием Spring у вас нет сеанса без него. Отсутствие сеанса вызовет исключение. Если я выполняю инструкцию 'INSERT' в jOOQ ** без **' @ Transactional' и выдаю исключение, запись сохраняется (нет отката). Но ** с ** '@ Transactional' выполняется откат. Я не совсем понимаю, почему это так. – displayname
Итак, главный вопрос: могу ли я использовать декларативные аннотации Springs с jOOQ и иметь вложенные транзакции, как я это делаю? Я бы предпочел использовать декларативные транзакции с использованием 'DSLContext.transaction()', чтобы иметь внутренние точки сохранения и откаты, если это возможно. – displayname
Да, вы можете использовать декларативные транзакции Spring без каких-либо проблем. jOOQ - это просто безопасный тип JDBC, поэтому, где бы вы не писали заявление JDBC, вы можете написать инструкцию jOOQ. Ничто в jOOQ не мешает этому. Просто поставьте jOOQ с любым «DataSource» из Spring, и вы настроены. Я подозреваю, что есть просто некоторая путаница вокруг того, что точка jOOQ 'TransactionProvider' ... –