在SpringBoot
中,我们可以将@EnableTransactionManagement
添加到应用程序类中,并将@Transactional
添加到相关的服务方法中,以使事务管理正常工作。
但是,我认为向每个需要事务的服务方法添加@Transactional
很无聊,我想像下面这样使用统一的方法来做到这一点(这意味着不使用@Transactional
):>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" rollback-for="Exception" propagation="REQUIRED"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="select*" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="service" expression="execution (* com.xxx.yyy.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="service"/>
</aop:config>
经过研究,我发现我们可以使用@ImportResource()
来导入xml配置文件。但是我想使用注释的方式来做,所以我在下面编写代码(ORM框架为mybatis
):
@Configuration
public class TransactionConfig {
@Bean("txInterceptor")
public TransactionInterceptor getInterceptor(PlatformTransactionManager tx) {
return new TransactionInterceptor(tx, transactionAttributeSource());
}
@Bean("txAdvisor")
public AspectJExpressionPointcutAdvisor pointcutAdvisor(TransactionInterceptor txInterceptor) {
AspectJExpressionPointcutAdvisor advisor = new AspectJExpressionPointcutAdvisor();
advisor.setAdvice(txInterceptor);
advisor.setExpression("execution (* com.xxx.yyy.service.*.*(..))");
return advisor;
}
@Bean("txSource")
public TransactionAttributeSource transactionAttributeSource() {
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
RuleBasedTransactionAttribute readyOnlyTx = new RuleBasedTransactionAttribute();
readyOnlyTx.setReadOnly(true);
readyOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
Map<String, TransactionAttribute> txMap = new HashMap<>();
txMap.put("find*", readyOnlyTx);
txMap.put("get*", readyOnlyTx);
txMap.put("select*", readyOnlyTx);
txMap.put("add*", requiredTx);
txMap.put("insert*", requiredTx);
txMap.put("update*", requiredTx);
txMap.put("delete*", requiredTx);
source.setNameMap(txMap);
return source;
}
}
测试代码:
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {
@Autowired
private IUserService userService;
@Test
public void testAddUser(){
UserModel uModel = new UserModel();
uModel.setUsername("vdu");
uModel.setPassword("123456");
uModel.setPhone("15112971150");
uModel.setEmail("vdu@mail.com");
uModel.setUserType(UserConstants.USER_TYPE_COMMON);
uModel.setRealName("Test User");
userService.addUser(uModel);
}
}
但是,当我运行测试代码时,我得到下面的输出,消息 com.mysql.jdbc.JDBC4Connection@63f6bed1]将不会由Spring管理,表明事务管理未启动。我在Google上搜索过,但仍然找不到解决方法,有人可以帮我分析一下吗?预先感谢!
[INFO ] 2019-05-22 17:30:00.534 下午 [main] PoolBase - HikariPool-1 - Driver does not support get/set network timeout for connections. (com.mysql.jdbc.JDBC4Connection.getNetworkTimeout()I)
[DEBUG] 2019-05-22 17:30:00.538 下午 [main] HikariPool - HikariPool-1 - Added connection com.mysql.jdbc.JDBC4Connection@63f6bed1
[INFO ] 2019-05-22 17:30:00.541 下午 [main] HikariDataSource - HikariPool-1 - Start completed.
[DEBUG] 2019-05-22 17:30:00.548 下午 [main] SpringManagedTransaction - JDBC Connection [HikariProxyConnection@1288163341 wrapping com.mysql.jdbc.JDBC4Connection@63f6bed1] will not be managed by Spring