非注解事务
<!-- 事务管理器-->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="c3p0DataSource" />
</bean>
bean id="c3p0DataSource"
class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- 不注册jmx -->
<!-- <constructor-arg type="boolean" value="false" /> -->
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/wjh"/>
<property name="user" value="root" />
<property name="password" value="root" />
</bean>
c3P0不能使用最新版本的,非注解的事务要使用老版本,新版本有bug,会报错,我使用0.8.4.5的,使用0.9.1.1会报空指针异常
业务层代码
@Resource(name="txManager")
private DataSourceTransactionManager tm;
public @ResponseBody String insert() {
TransactionTemplate tran =
new TransactionTemplate(tm);
return tran.execute(new TransactionCallback<String>() {
@Override
public String doInTransaction(TransactionStatus status) {
User user = new User();
user.setEmail("223@qq.com");
user.setPassword("123");
user.setNickname("weck");
UserInfo info = new UserInfo();
info.setUser(user);
info.setAge(16);
info.setSex("男");
userMapper.saveUser(user);
userMapper.saveUserInfo(info);
return "ok";
}
});
}
如果不想有返回值可以这么写
TransactionTemplate tran =
new TransactionTemplate(tm);
tran.execute(new TransactionCallbackWithoutResult() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
User user = new User();
user.setEmail("223@qq.com");
user.setPassword("123");
user.setNickname("weck");
UserInfo info = new UserInfo();
info.setUser(user);
info.setAge(16);
info.setSex("男");
userMapper.saveUser(user);
userMapper.saveUserInfo(info);
//return "ok";
}
});
在非注解事务中,我们可以设置事务保存点
TransactionTemplate tran =
new TransactionTemplate(tm);
tran.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus tran) {
Object obj = tran.createSavepoint(); //创建事务保存点
tran.releaseSavepoint(obj); //释放保存点
tran.rollbackToSavepoint(obj); //回滚到保存点
}
});
注解事务
需要aopalliance-1.0.jar
在spring-mvc.xml文件中
<!-- 事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="c3p0DataSource" />
</bean>
<!-- 事务注解驱动,标注@Transactional的类和方法将具有事务性 -->
<tx:annotation-driven transaction-manager="txManager" />
注意:transactionManager是事务默认id,transaction-manager=”transactionManager”这个属性省略不写
<!-- 事务管理器-->
<bean id=""transactionManager""
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 事务注解驱动,标注@Transactional的类和方法将具有事务性 -->
<tx:annotation-driven />
处理业务代码
@RequestMapping(value="/insert",produces="text/html;charset=utf-8")
@Transactional
public @ResponseBody String insert(){
User user = new User();
user.setEmail("223@qq.com");
user.setPassword("123");
user.setNickname("weck");
UserInfo info = new UserInfo();
info.setUser(user);
info.setAge(16);
info.setSex("男");
userMapper.saveUser(user);
userMapper.saveUserInfo(info);
return "ok";
}
只要加了@Transactional,会自动执行事务,一但在一个中间某处业务出错,不会被提交,数据库便不会插入任何信息,声明式事务管理是利用Spring AOP实现的,注解的使用简单,对代码没有侵入性,逻辑更清晰
@Transactional标记有以下属性,在使用时可以根据需要做特殊设定
- propagation 设置事务传播
- isolation 设置事务隔离级别
- timeout 设置超时时间
- readOnly 设置为只读
- rollbackFor 或 rollbackForClassName 设置哪些异常回滚
- noRollbackFor 或 noRollbackForClassName 设置哪些异常不回滚
@Transactional 注解属性默认设置如下:
- 事务传播设置是 Propagation.REQUIRED
- 事务隔离级别是 Isolation.DEFAULT
- 事务可读写
- 事务超时默认依赖事务系统的,或者事务超时没有被支持
- 任何RuntimeException 将触发事务回滚,但是任何Checked Exception 将不触发事务回滚
在xml中实现声明式事务
<tx:advice id="txAdvice" transaction-manager="txManager" >
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<aop:config proxy-target-class="true">
<aop:advisor advice-ref="txAdvice" pointcut="within(spring.controller..*)" />
</aop:config>
事务的回滚异常
异常分类
- 检查异常(编译异常)
- 运行时异常
运行时异常直接回退,检查异常需要指定回退
对于Checked Exception,需要手动指定异常类型,才能实现事务回滚
使用注解声明式事务,如下方式指定异常:
@Transactional(rollbackFor=ClassNotFoundException.class)
使用xml配置声明式事务如下:
<tx:method name="update*" propagation="REQUIRED"
rollback-for="java.lang.ClassNotFoundException"/>
<tx:method name="find*" read-only="true" isolation="READ_COMMITTED" />
设置隔离级别为读取提交的数据