Spring中Transactional注解的使用:
@Transactional(propagation=Propagation.REQUIRED,rollbackFor = Exception.class) 已经有事务则直接加入,没有事务则新建事务;遇到异常则回滚
1)定义事物传播行为介绍:
@Transactional(propagation=Propagation.REQUIRED) :如果有事务, 那么加入事务, 没有的话新建一个(默认情况下) @Transactional(propagation=Propagation.REQUIRES_NEW) :不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY) :必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER) :必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) :如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
@Transactional(propagation=Propagation.NOT_SUPPORTED) :容器不为这个方法开启事务
2)事物超时设置:
@Transactional(timeout=30) //默认是30秒
3)事务隔离级别:
@Transactional(isolation = Isolation.READ_UNCOMMITTED):读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED):读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ):可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE):串行化
MYSQL: 默认为REPEATABLE_READ级别
SQLSERVER: 默认为READ_COMMITTED
4)定义事物遇到哪些异常会回滚(rollback)
在Spring中,@Transactional默认遇到运行时异常(RuntimeException)和错误(Error)时会回滚事务。具体来说,当方法抛出任何继承自RuntimeException的异常或Error时,Spring会自动回滚事务。如果抛出的是checked异常(非RuntimeException),则默认情况下不会回滚事务,需要使用rollbackFor属性指定需要回滚的异常类型。
在Java中,异常分为两种类型:checked异常和unchecked异常。
Checked异常是指在编译时必须处理的异常,即在方法声明中必须声明或捕获的异常。例如,IOException、SQLException等都是checked异常。如果不处理这些异常,编译器会报错。
Unchecked异常是指在编译时不需要处理的异常,即不需要在方法声明中声明或捕获的异常。例如,NullPointerException、ArrayIndexOutOfBoundsException等都是unchecked异常。如果不处理这些异常,程序会在运行时抛出异常。
通常情况下,我们应该尽可能地使用checked异常,因为它们可以提醒程序员在编写代码时必须考虑异常情况,从而编写更加健壮的代码。而unchecked异常则通常是由程序员的错误导致的,应该尽可能避免出现这种异常。
5)使用注意点
a @Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
b 如果方法save中使用了事务,但是方法get被声明了不支持事务,在方法save中调用了方法get,此时会出现save中插入的记录在get中查询不到。不允许支持事务的配置可能如下:
Ssm框架下使用数据库的事物:
首先确认数据库的引擎类型,如果是myisam则不支持使用事物,修改为InnoDB支持事物.
show engines;//查看数据库引擎 类型
alter table task_baseinfo type=innodb;//修改task_baseinfo引擎类型为innodb
1. spring的配置文件中 声明 和 开启 事物管理
<!-- 开启事物管理 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynamicDataSource" />
</bean>
2)对公共方法增加事物管理
// @Transactional(readOnly=false,propagation=Propagation.REQUIRED,rollbackFor = Exception.class)
@Transactional
@Override
public int saveTaskBaseInfo(int taskId, String taskName, int taskType,
int funcNum, String lastModifiedUser,String allbefroeTaskId, String startDate,int startTime,int endTime) {
// 如果任务中包含有 taskId则执行修改
//新插入执行的操作
int newTaskId=getMaxTaskId()+1;
taskId = newTaskId ;
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("table_name", "task_baseinfo");
map.put("col_name", "task_id,task_name,task_type,create_time,last_modified_user,isdel");
map.put("col_value", "("+newTaskId+",'"+taskName+"',"+taskType+",'"+DateUtil.getNowDateAsStr()+"','"+lastModifiedUser+"'"+",0"+")");
mysqlAlterService.addRecord(map);//第一个插入操作
int recode=taskTimeInfoService.insertTaskTimeInfo(taskId, startDate, startTime, endTime);//第二个插入操作,如果插入有问题,则返回的值为负数
if(recode<0){
throw new RuntimeException("该任务的定时信息插入失败...");//此处抛出的RuntimeException十分重要,只有抛出了该异常才会调用事物管理,此时抛出运行时异常说明第二个插入有问题.所以两个插入均失败;虽然第一个插入操作已经执行,但是此时会自动回滚.
}
return 1000;
}