执子之手

与子偕老


  • 首页

  • 分类

  • 归档

  • 标签

  • 关于

  • 搜索
close

迁移到SpringBoot 05 - 事务管理

时间: 2018-06-01   |   分类: 开发     |   阅读: 1368 字 ~3分钟   |   访问: 0

Spring项目中使用数据库的方式多种多样,注入MyBatis、JDBC、Hibernate等等都是支持的。之前的系统是基于MyBatis的。

关于如何Spring Boot和MyBatis网上有很多文章,可以参考。有时间我也会专门写一篇介绍集成的过程。本文讲的就是MyBatis移植到Spring Boot方面碰到的一些问题,主要是事务控制方面的。

1. Spring原始配置

在Spring中,之前是通过XML方式进行的事务配置。通过tx:advice定义了事务的属性;然后通过aop:config将事务织入业务代码。

 1<!-- from the file 'context.xml' -->
 2<?xml version="1.0" encoding="UTF-8"?>
 3<beans xmlns="http://www.springframework.org/schema/beans"
 4    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5    xmlns:aop="http://www.springframework.org/schema/aop"
 6    xmlns:tx="http://www.springframework.org/schema/tx"
 7    xsi:schemaLocation="
 8        http://www.springframework.org/schema/beans
 9        http://www.springframework.org/schema/beans/spring-beans.xsd
10        http://www.springframework.org/schema/tx
11        http://www.springframework.org/schema/tx/spring-tx.xsd
12        http://www.springframework.org/schema/aop
13        http://www.springframework.org/schema/aop/spring-aop.xsd">
14
15    <!-- this is the service object that we want to make transactional -->
16    <bean id="fooService" class="x.y.service.DefaultFooService"/>
17
18    <!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean below) -->
19    <tx:advice id="txAdvice" transaction-manager="txManager">
20        <!-- the transactional semantics... -->
21        <tx:attributes>
22            <!-- all methods starting with 'get' are read-only -->
23            <tx:method name="get*" read-only="true"/>
24            <!-- other methods use the default transaction settings (see below) -->
25            <tx:method name="*"/>
26        </tx:attributes>
27    </tx:advice>
28
29    <!-- ensure that the above transactional advice runs for any execution
30        of an operation defined by the FooService interface -->
31    <aop:config>
32        <aop:pointcut id="fooServiceOperation" expression="execution(* x.y.service.FooService.*(..))"/>
33        <aop:advisor advice-ref="txAdvice" pointcut-ref="fooServiceOperation"/>
34    </aop:config>
35
36    <!-- don't forget the DataSource -->
37    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
38        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
39        <property name="url" value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
40        <property name="username" value="scott"/>
41        <property name="password" value="tiger"/>
42    </bean>
43
44    <!-- similarly, don't forget the PlatformTransactionManager -->
45    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
46        <property name="dataSource" ref="dataSource"/>
47    </bean>
48
49    <!-- other <bean/> definitions here -->
50
51</beans>

2. 迁移到SpringBoot

迁移到SpringBoot还是倾向于使用基于Java的配置,因此最初的想法是完全跑起xml配置文件。但是在实践中发现了一些限制:<aop:config>标签无法完整准确的翻译成Java配置。

2.1 限制

通过上网搜索,发现解决方案并不完美:

The @Aspect model in AspectJ is designed for pure-Java configuration, and should be used in favor of aop:config when looking to create 100% java-based configuration using Spring’s @Configuration model. aop:config cannot properly be translated into the @Configuration model, largely because Java does not support method literals in the language. This leaves us resorting to String-based references to methods, which is not ideal. So the approach that users should consider are:

  1. Continue using aop:config by including the relevant XML snippet using @ImportResource
  2. Convert any existing aop:config elmements to use @Aspect style.

上面推荐的方案有两种:

  1. 继续使用xml配置,然后通过 @ImportResource注解导入Java代码中;
  2. 转换<aop:config>配置成@Aspect注解。

2.2 最终方案

因为时间的原因,对@Aspect形式的配置没有做深入研究。另外从StackOverflow上查到的说法是,tx-advice并没有合适的Java配置方法,使用xml配置还是最方便的。只是xml配置通过@Configuration中的@ImportResource注解引入即可,这样还是比较优雅,比较符合Java配置的规范性的。因此最终方案是使用了部分xml配置,通过@ImportResource引入。

2.2.1 MasterDataSourceConfig

 1@Configuration
 2public class MasterDataSourceConfig {
 3    static final String PACKAGE = "com.eveus.iot.shadow.mapper";
 4    static final String MAPPER_LOCATION = "classpath:mybatis/mapper/**/*.xml";
 5
 6    @Bean
 7    @Primary
 8    @ConfigurationProperties("spring.datasource")
 9    public DataSourceProperties firstDataSourceProperties() {
10        return new DataSourceProperties();
11    }
12
13    @Bean(name = "masterDataSource")
14    @Primary
15    @ConfigurationProperties(prefix = "spring.datasource")
16    public DataSource dataSource() {
17        return firstDataSourceProperties().initializeDataSourceBuilder().build();
18    }
19
20    @Bean(name = "masterTransactionManager")
21    public DataSourceTransactionManager transactionManager() {
22        return new DataSourceTransactionManager(dataSource());
23    }
24
25
26    @Bean(name = "masterSqlSessionFactory")
27    public SqlSessionFactory sqlSessionFactory(@Qualifier("masterDataSource") DataSource masterDataSource)
28            throws Exception {
29        final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
30        sessionFactory.setDataSource(masterDataSource);
31        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
32                .getResources(MasterDataSourceConfig.MAPPER_LOCATION));
33        return sessionFactory.getObject();
34    }
35}

定义dataSource, transactionManager。

2.2.2 TransactionConfig

1...
2@Configuration
3@Aspect
4@ComponentScan("com.eveus.cloudauth")
5@ImportResource("classpath:/spring/uid-tx.xml")
6public class TransactionConfig {
7}

引入xml配置。

2.2.3 uid-tx.xml

 1<?xml version="1.0" encoding="UTF-8"?>
 2<beans xmlns="http://www.springframework.org/schema/beans"
 3       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4       xmlns:aop="http://www.springframework.org/schema/aop"
 5       xmlns:tx="http://www.springframework.org/schema/tx"
 6       xsi:schemaLocation="http://www.springframework.org/schema/beans
 7       http://www.springframework.org/schema/beans/spring-beans.xsd
 8
 9       http://www.springframework.org/schema/aop
10       http://www.springframework.org/schema/aop/spring-aop.xsd
11       http://www.springframework.org/schema/tx
12       http://www.springframework.org/schema/tx/spring-tx.xsd">
13
14    <!-- AOP -->
15    <tx:advice id="merchantTransactionAdvice" transaction-manager="masterTransactionManager">
16        <tx:attributes>
17            <tx:method name="insert*" propagation="REQUIRED" />
18            <tx:method name="update*" propagation="REQUIRED" />
19            <tx:method name="delete*" propagation="REQUIRED" />
20            <tx:method name="lock*" propagation="REQUIRED" />
21            <tx:method name="unlock*" propagation="REQUIRED" />
22
23            <tx:method name="select*" propagation="SUPPORTS" />
24            <tx:method name="list*" propagation="SUPPORTS" />
25
26            <tx:method name="*" propagation="SUPPORTS" />
27        </tx:attributes>
28    </tx:advice>
29    <aop:config>
30        <aop:pointcut id="merchantTransactionPointcut" expression="execution(* com.eveus.cloudauth.dal.mybatis.MerchantDalImpl.*(..))" />
31        <aop:advisor pointcut-ref="merchantTransactionPointcut" advice-ref="merchantTransactionAdvice" />
32    </aop:config>
33	...
34</beans>

如上配置中:transactionManager是在Java配置中定义的。其他的和原先的xml配置没有区别。

附录A. 参考资料

  • Introduce @Configuration-based equivalent to aop:config XML element
  • JavaConfig: Replacing aop:advisor and tx:advice
  • Aspect Oriented Programming with Spring
  • Spring事务管理(详解+实例)
  • Spring Declarative Transaction Management Example
  • Spring AOP : Replace XML with annotations for transaction management?
  • 零xml配置Spring事务管理
#Spring# #Springboot#
Spring使用POI导出Excel内存溢出问题的解决
迁移到SpringBoot 04 - Redis
  • 文章目录
  • 站点概览
Orchidflower

Orchidflower

Do one thing at a time, and do well.

77 日志
6 分类
84 标签
GitHub 知乎 OSC 豆瓣
  • 1. Spring原始配置
  • 2. 迁移到SpringBoot
    • 2.1 限制
    • 2.2 最终方案
      • 2.2.1 MasterDataSourceConfig
      • 2.2.2 TransactionConfig
      • 2.2.3 uid-tx.xml
  • 附录A. 参考资料
© 2009 - 2024 执子之手
Powered by - Hugo v0.113.0
Theme by - NexT
ICP - 鲁ICP备17006463号-1
0%