【Spring】声明式事务管理(十五)


步骤:

1) 引入spring-aop相关的4jar文件

2) 引入aop名称空间  【XML配置方式需要引入】

3) 引入tx名称空间    【事务方式必须引入】

XML方式实现


1. DeptDao.java

public class DeptDao {
// 容器注入JdbcTemplate对象
private JdbcTemplate jdbcTemplate;
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
 
public void save(Dept dept){
String sql = "insert into t_dept (deptName) values(?)";
jdbcTemplate.update(sql,dept.getDeptName());
}
}


2. DeptService

public class DeptService {
// 容器注入dao对象
private DeptDao deptDao;
public void setDeptDao(DeptDao deptDao) {
this.deptDao = deptDao;
}
 
/*
 * 事务控制?
 */
public void save(Dept dept){
// 第一次调用
deptDao.save(dept);
int i = 1/0; // 异常: 整个Service.save()执行成功的要回滚
// 第二次调用
deptDao.save(dept);
}
}

3. App  测试类

@Test
public void testApp() throws Exception {
//容器对象
ApplicationContext ac = new ClassPathXmlApplicationContext("cn/lfsfenior/a_tx/bean.xml");
// 模拟数据
Dept dept = new Dept();
dept.setDeptName("测试: 开发部");
DeptService deptService = (DeptService) ac.getBean("deptService");
deptService.save(dept);
} 


4. bean.xml  (Spring 声明式事务管理配置 )



 



















 






















     

 

注解方式实现

使用注解实现Spring的声明式事务管理,更加简单!

步骤:

1) 必须引入Aop相关的jar文件

2bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类

3)在需要添加事务控制的地方,写上: @Transactional

 

@Transactional注解:

1)应用事务的注解

2)定义到方法上: 当前方法应用spring的声明式事务

3)定义到类上:   当前类的所有的方法都应用Spring声明式事务管理;

4)定义到父类上: 当执行父类的方法时候应用事务。

 Bean.xml



 























     

DeptService


@Service
public class DeptService {
@Resource
private DeptDao deptDao;
 
/*
 * 事务控制?
 */
@Transactional
public void save(Dept dept){
deptDao.save(dept);
int i = 1/0;
deptDao.save(dept);
}
}



  

事务属性

@Transactional(
readOnly = false,  // 读写事务
timeout = -1,       // 事务的超时时间不限制
noRollbackFor = ArithmeticException.class,  // 遇到数学异常不回滚
isolation = Isolation.DEFAULT,              // 事务的隔离级别,数据库的默认
propagation = Propagation.REQUIRED	// 事务的传播行为
)
public void save(Dept dept){
deptDao.save(dept);
int i = 1/0;
deptDao.save(dept);
}




事务管理级别: 

DEFAULT

使用后端数据库默认的隔离级别(spring中的的选择项)

READ_UNCOMMITED

允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读

READ_COMMITTED

允许在并发事务已经提交后读取。可防止脏读,但幻读和 不可重复读仍可发生

REPEATABLE_READ

对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。

SERIALIZABLE

完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

 

事务传播行为:

REQUIRED

业务方法需要在一个事务中运行。如果方法运行时,已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务

NOT_SUPPORTED

声明方法不需要事务。如果方法没有关联到一个事务,容器不会为它开启事务。如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行

REQUIRESNEW

属性表明不管是否存在事务,业务方法总会为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务会被挂起,新的事务会被创建,直到方法执行结束,新事务才算结束,原先的事务才会恢复执行

MANDATORY

该属性指定业务方法只能在一个已经存在的事务中执行,业务方法不能发起自己的事务。如果业务方法在没有事务的环境下调用,容器就会抛出例外。

SUPPORTS

这一事务属性表明,如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分。如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行

Never

指定业务方法绝对不能在事务范围内执行。如果业务方法在某个事务中执行,容器会抛出例外,只有业务方法没有关联到任何事务,才能正常执行

NESTED

如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按REQUIRED

属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效

 

Propagation.REQUIRED

指定当前的方法必须在事务的环境下执行;

如果当前运行的方法,已经存在事务, 就会加入当前的事务;

Propagation.REQUIRED_NEW

指定当前的方法必须在事务的环境下执行;

如果当前运行的方法,已经存在事务:  事务会挂起; 会始终开启一个新的事务,执行完后;  刚才挂起的事务才继续运行。

 

 

举例:

Class Log{

Propagation.REQUIRED  

insertLog();  

}

 

Propagation.REQUIRED

Void  saveDept(){

insertLog();    // 加入当前事务

.. 异常, 会回滚

saveDept();

}

 

 

Class Log{

Propagation.REQUIRED_NEW  

insertLog();  

}

 

Propagation.REQUIRED

Void  saveDept(){

insertLog();    // 始终开启事务,因为是新事物,所有会插入日志

.. 异常, 日志不会回滚

saveDept();

}

你可能感兴趣的:(lfsenior,spring,------,【Spring】,Spring)