Spring 学习(六)事务管理

Spring事务管理:事务应该在service层统一控制

开发步骤:

  1. 后台环境准备:数据库、表/entity/dao/service
  2. dao实现:使用spring对JDBC模块的支持:JdbcTemplate
  3. 对象创建由Spring容器完成

一、事务控制分类:

编程式事务控制:可以实现细粒度的事务控制,但是开发效率较低,且事务管理和代码耦合度高

Jdbc:conn.setAutoCommit(false);
Hibernate:Session.beginTransaction();

声明式事务控制:Spring提供的对事物的管理,当不需要细粒度事务管理时,可以通过配置文件来实现。基于AOP,实现了事务控制和代码的解耦。但是不能实现对某个方法中特定几行代码应用事务,是粗粒度的事务控制。(AOP拦截的是方法)

二、Spring声明式事务控制

事务管理器类:
Jdbc技术:DataSourceTransactionManager;
Hibernate技术:HibernateTransactionManager;

1. XML实现Jdbc技术:



    




    
        
        
        
    




    
    
 

因此,对DeptService中的所有方法实现了事务管理,切面类由“org.springframework.jdbc.datasource.DataSourceTransactionManager”实现,save()方法中执行到int i = 1/0;抛出异常,事务回滚,数据库中没有变化。如果不配置事务管理,数据库中会存入一条数据!

public class DeptService {
    private DeptDao deptDao;
    public void setDeptDao(DeptDao deptDao) {
        this.deptDao = deptDao;
    }
    public void save(Dept dept){
        deptDao.save(dept);
        int i=1/0;//异常:java.lang.ArithmeticException: / by zero
        deptDao.save(dept);
    }
}

2. 注解实现Jdbc技术:

配置:


    

    
        
        
        
        
        
        
        
        
    

    
        
    

    
    
        
    

    
    
    

在Service中对需要应用事务管理的方法,或者类注解(类中所有方法都应用Spring声明式事务管理)即可。

特殊情况可以定义在父类上,执行父类中的方法时,应用事务。

@Service
public class DeptService {
    @Resource
    private DeptDao deptDao;
    public void setDeptDao(DeptDao deptDao) {
        this.deptDao = deptDao;
    }
    @Transactional
    public void save(Dept dept){
        deptDao.save(dept);
        int i=1/0;
        deptDao.save(dept);
    }
}

三、事务属性

@Transactional(
            readOnly=false //只读状态,优化查询
            ,timeout=-1//超时时间,-1表示不限制,最终是由数据库底层配置起作用的,这里设置不一定起作用
            ,noRollbackFor=ArithmeticException.class//遇到数学异常,不回滚
            ,isolation=Isolation.DEFAULT//事务隔离级别,数据库默认
            ,propagation=Propagation.REQUIRED//事务传播行为,当前方法时是否需要在事务中执行
            //Propagation.REQUIRED     :当前运行的方法中,如果存在子事务,会与现有事务合并;
            //Propagation.REQUIRED_NEW :当前运行的方法中,如果存在子事务,当前事务挂起,执行完子事务后,再执行该事务,自事务和现有事务不相互影响;
            )

一句话:被Propagation.REQUIRED_NEW属性修饰的事务,事务不受别人影响。案例:

新建一组service和dao,用于dept表操作的日志:

建表:

CREATE TABLE t_logInfo(
    content VARCHAR(20)
);

dao:

@Repository
public class LogDao {
    @Resource
    private JdbcTemplate jdbcTemplate;

    public void insert(){
        jdbcTemplate.update("insert into t_logInfo values('saving into log!!!');");
    }
}

service:

@Service
public class LogService {
    @Resource
    private LogDao logDao;

    @Transactional(propagation=Propagation.REQUIRED)
    public void insert(){
        logDao.insert();
    }
}

修改DeptService:

@Service
public class DeptService {
    @Resource
    private DeptDao deptDao;
    @Resource
    private LogService logService;

    @Transactional
    public void save(Dept dept){
        logService.insert();
        int i=1/0;
        deptDao.save(dept);
    }
}

由于logService的事务传播行为定义为“propagation=Propagation.REQUIRED”,即,事务存在传播行为;因此,数据插入不成功时,日志也不记录。如果修改日志插入的事务传播行为:

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void insert(){
    logDao.insert();
}

则,日志成功记录,即使数据没有成功保存。

你可能感兴趣的:(Spring,spring,事务)