spring3 事务处理
先让我们看代码吧!
以下代码为在“Spring3事务管理——基于tx/aop命名空间的配置”基础上修改。首先修改applicationContext.xml如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
… <!-- 定义一个数据源 --> < bean id = "dataSource" class = "org.apache.tomcat.jdbc.pool.DataSource" > < property name = "driverClassName" value = "com.mysql.jdbc.Driver" /> < property name = "url" value = "jdbc:mysql://localhost:3306/spring_test" /> < property name = "username" value = "root" /> < property name = "password" value = "root" /> </ bean > <!-- 定义JdbcTemplate的Bean --> < bean id = "jdbcTemplate" class = "org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref = "dataSource" > </ bean > <!-- 配置事务管理器 --> < bean id = "txManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref = "dataSource" > </ bean > <!-- enables scanning for @Transactional annotations --> < tx:annotation-driven transaction-manager = "txManager" /> <!-- 在该Bean的代码中标注@Transactional可以被事务管理器注入 --> < bean id = "userScore" class = "net.hingyi.springDemo.transaction.service.UserScoreServiceImpl" p:userScoreRepository-ref = "userScoreRepository_jdbc" /> < bean id = "userScoreRepository_jdbc" class = "net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl" p:jdbcTemplate-ref = "jdbcTemplate" /> … |
实现类代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Transactional public class UserScoreRepositoryImpl implements UserScoreRepository { private JdbcTemplate jdbcTemplate; @Override public UserScore getUserSocore(String userNo) { final UserScore us = new UserScore(); ... return us; } ... } |
OK了!以上就实现了简单的事务管理了。现在再稍微了解下@Transactional。
在配置文件中,默认情况下,<tx:annotation-driven>会自动使用名称为transactionManager的事务管理器。所以,如果定义的事务管理器名称为transactionManager,那么就可以直接使用<tx:annotation-driven/>。如下:
1
2
3
4
5
6
7
8
|
<!-- 配置事务管理器 --> < bean id = "transactionManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref = "dataSource" > </ bean > <!-- enables scanning for @Transactional annotations --> < tx:annotation-driven /> |
<tx:annotation-driven>一共有四个属性如下,
- mode:指定Spring事务管理框架创建通知bean的方式。可用的值有proxy和aspectj。前者是默认值,表示通知对象是个JDK代理;后者表示Spring AOP会使用AspectJ创建代理
- proxy-target-class:如果为true,Spring将创建子类来代理业务类;如果为false,则使用基于接口的代理。(如果使用子类代理,需要在类路径中添加CGLib.jar类库)
- order:如果业务类除事务切面外,还需要织入其他的切面,通过该属性可以控制事务切面在目标连接点的织入顺序。
- transaction-manager:指定到现有的PlatformTransaction Manager bean的引用,通知会使用该引用
@Transactional的属性
属性名 |
类型 |
说明 |
isolation |
枚举org.springframework.transaction.annotation.Isolation的值 |
事务隔离级别 |
noRollbackFor |
Class<? extends Throwable>[] |
一组异常类,遇到时不回滚。默认为{} |
noRollbackForClassName |
Stirng[] |
一组异常类名,遇到时不回滚,默认为{} |
propagation |
枚举org.springframework.transaction.annotation.Propagation的值 |
事务传播行为 |
readOnly |
boolean |
事务读写性 |
rollbackFor |
Class<? extends Throwable>[] |
一组异常类,遇到时回滚 |
rollbackForClassName |
Stirng[] |
一组异常类名,遇到时回滚 |
timeout |
int |
超时时间,以秒为单位 |
value |
String |
可选的限定描述符,指定使用的事务管理器 |
@Transactional标注的位置
@Transactional注解可以标注在类和方法上,也可以标注在定义的接口和接口方法上。
如果我们在接口上标注@Transactional注解,会留下这样的隐患:因为注解不能被继承,所以业务接口中标注的@Transactional注解不会被业务实现类继承。所以可能会出现不启动事务的情况。所以,Spring建议我们将@Transaction注解在实现类上。
在方法上的@Transactional注解会覆盖掉类上的@Transactional。
使用不同的事务管理器
如果我们要程序中使用多个事务管理器(主要是针对多数据源的情况),可以通过以下的方式实现:
Service代码:
1
2
3
4
5
6
7
8
9
10
11
|
public class MultiTxService { @Transactional ( "tran_1" ) public void addTest( int id){ } @Transactional ( "tran_2" ) public void deleteTest( int id){ } } |
applicationContext.xml配置如下:
1
2
3
4
5
6
7
8
9
10
|
< bean id = "tran_1" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref = "dataSource" > < qualifier value = "tran_1" /> </ bean > < bean id = "tran_2" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref = "dataSource" > < qualifier value = "tran_2" /> </ bean > |
经过以上的代码,每个事务都会绑定各自的独立的数据源,进行各自的事务管理。我们可以优化下以上代码,可以自定义一个绑定到特定事务管理器的注解,然后直接使用这个自定义的注解进行标识:
1
2
3
4
5
6
|
@Target ({ElementType.METHOD,ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @Transactional ( "tran_1" ) public @interface CustomerTransactional { } |
在Service代码中使用:
1
2
3
4
5
6
7
|
... //使用名为tran_1的事务管理器 @CustomerTransactional public void addTest(String str){ } … |
转自:http://my.oschina.net/guanzhenxing/blog/214228
ORM用JPA的事务处理:
2. 使用@Transactional的Spring配置
为了使用基于@Transactional的事务管理,需要在Spring中进行如下的配置:
- <beans:bean id="transactionManager"
- class="org.springframework.orm.jpa.JpaTransactionManager">
- <beans:property name="dataSource" ref="dataSource" />
- <beans:property name="entityManagerFactory" ref="entityManagerFactory" />
- </beans:bean>
- <!-- 声明使用注解式事务 -->
- <tx:annotation-driven transaction-manager="transactionManager" />
dataSource是在Spring配置文件中定义的数据源的对象实例,EntityManagerFactory是基于JPA使用的实体类管理器:org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean。这些都是用来配置与数据库的连接信息,本质上,@Transactional使用了JDBC的事务来进行事务控制的。
<annotation-driven>标签的声明,则是在Spring内部启用@Transactional来进行事务管理,类似开关之类的声明。