博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring事务管理
阅读量:7281 次
发布时间:2019-06-30

本文共 6137 字,大约阅读时间需要 20 分钟。

一、什么是事务

  事务:指逻辑上的一组操作,这组操作要么全部成功,要么全部失败。有以下特性:

原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性:事务前后数据的完整性必须保持一致(张三给李四转账,张三+李四的总额不变)。
隔离性:多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务干扰,多个并发事务之间的数据相互隔离。
持久性:一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不该对其有任何影响。

二、事务管理接口

  Spring的事务管理接口主要有三个:

  ①TransactionDefinition,事务定义信息(隔离,传播,超时,只读)

  在Spring中,事务是通过TransactionDefinition接口来定义的,该接口包含与事务属性相关的方法,TransactionDefinition定义了五个表示隔离级别的常量,代表传播行为的常量,在TransactionDefinition中以int值表示超时时间。

  • 隔离:防止数据库脏读、虚读等行为
  • 传播:解决业务层方法之间的调用,传递事务
    • 情形一,支持当前事务,如果不存在就创建一个;
    • 情形二,如果有事务存在,挂起当前事务,创建一个新事务;
    • 情形三,如果当前事务存在,嵌套事务执行。

  这里找到一篇关于TransactionDefinition的文章:

  Platform TransactionManager,平台事务管理器

  Spring为不同的持久化框架提供了不同的平台事务管理器的接口实现:

  • 使用Spring JDBC或者IBatis进行持久化数据时:org.springframework.jdbc.datasource.DataSourceTransactionManager
  • 使用Hibernate5.0版本进行持久化数据时:org.springframework.orm.hibernate5.HibernateTransactionManager

  Platform TransactionManager.getInstance()方法返回一个Transaction Status对象,返回的Transaction Status对象可能代表一个新的或已经存在的事务(如果当前调用堆栈中有一个符合条件的事务)。  

  ③TransactionStatus,事务具体运行状态

  Transaction Status接口提供了一个简单的控制事务查询和执行的方法。

三、Spring事务管理的方式

  Spring的事务管理有两种方式:

  ①编程式的事务管理:编程式即采用注解的方式,需要注意的是,使用注解的方式需要在Spring的配置文件中加入一句话:<context:annotation-config />,其作用是开启注解的方式。这种方式在实际应用开发中很少使用,通过TransactionTemlate手动管理事务。

  ②使用XML配置声明式事务:声明式就是在Spring的配置文件中进行相关配置,Spring的声明式事务是通过AOP实现的,实质就是在方法执行前后进行拦截,然后在方法执行前创建并加入事务,执行完目标方法后根据执行情况提交事务或者回滚事务。开发中推荐使用(代码侵入性最小)。

  Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSourceTransactionManager代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 DataSource、 TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为 SessionFactory,TransactionManager的实现为HibernateTransactionManager。

四、转账案例

  ①编程式的事务控制

  •  在AccountService中使用TransactionTemplate
  •  TransactionTemplate依赖HibernateTransactionManager
  • HibernateTransactionManager依赖LocalSessionFactoryBean
org.hibernate.dialect.OracleDialect
update
true
true
@Repository("accountDAO")/* 转账案例的DAO层接口实现类 */public class AccountDAOImpl implements AccountDAO {    @Autowired    private SessionFactory sessionFactory;    public SessionFactory getSessionFactory() {        return sessionFactory;    }    /**     *      * @param out     *            转出帐号     * @param money     *            转出金额     */    @Override    public void outMoney(String out, double money) {        Session session = sessionFactory.getCurrentSession();        String hql = "from Account where name = :name";        Query query = session.createQuery(hql);        query.setString("name", out);        Account account = (Account) query.uniqueResult();        account.setMoney(account.getMoney() - money);        session.save(account);    }    /**     *      * @param in     *            转入帐号     * @param money     *            转入金额     */    @Override    public void inMoney(String in, double money) {        Session session = sessionFactory.getCurrentSession();        String hql = "from Account where name = :name";        Query query = session.createQuery(hql);        query.setString("name", in);        Account account = (Account) query.uniqueResult();        account.setMoney(account.getMoney() + money);        session.save(account);    }}
@Service("accountService")public class AccountServiceImpl implements AccountService {    @Autowired    private AccountDAO accountDAO;    // 注入事务模板    @Autowired    private TransactionTemplate transactionTemplate;    /**     *      * @param out     *            转出帐号     * @param in     *            转入帐号     * @param money     *            转账金额     */    @Override    public void transfer(final String out, final String in, final double money) {        // 模版回调处理事务        this.transactionTemplate.execute(new TransactionCallbackWithoutResult() {             @Override             protected void doInTransactionWithoutResult(                   TransactionStatus transactionStatus) {                   try {                        accountDAO.outMoney(out, money);                        // int i = 1 / 0;// 异常会导致入账失败                        accountDAO.inMoney(in, money);                   } catch (Exception e) {                        System.out.println(e.getMessage());                        transactionStatus.setRollbackOnly();// 事务回滚                   }             }         });    }}

  ②声明式的事务控制

  • 第一种方式:基于TransactionProxyFactoryBean
PROPAGATION_REQUIRED
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration("classpath:spring-account2.xml")public class UnitTest {    /**     * 注入代理类     */    @Resource(name = "accountServiceProxy")    private AccountService accountService;    /**     * 注入工厂     */    @Resource    private SessionFactory sessionFactory;    @Test    public void testAccount() {        accountService.transfer("张三", "李四", 200);    }}
  • 第二种方式:基于AspectJ的XML配置方式(经常使用,配置清晰)
  • 第三种方式:基于注解方式(经常使用,配置简单)
@Service("accountService")@Transactional// (propagation="",isolation="",readOnly="",noRollbackFor="",rollbackFor="",timeout="")public class AccountServiceImpl implements AccountService {    @Autowired    private AccountDAO accountDAO;    /**     *      * @param out     *            转出帐号     * @param in     *            转入帐号     * @param money     *            转账金额     */    @Override    public void transfer(String out, String in, double money) {        accountDAO.outMoney(out, money);        int i = 1 / 0;// 异常会导致入账失败        accountDAO.inMoney(in, money);    }}

  注:找到一篇关于Spring事务管理的写得挺好的文章:

 

转载于:https://www.cnblogs.com/ToukoXu/p/7871795.html

你可能感兴趣的文章
基于MFC和opencv的FFT
查看>>
0823模拟赛
查看>>
Ajax
查看>>
HDU 1849 Rabbit and Grass 【Nim博弈】
查看>>
JMeter-Java压力测试工具-01
查看>>
搜狐在线笔试 时间复杂度O(n)实现数组A[n]中所有元素循环左移k个位置
查看>>
写python时加入缩进设置
查看>>
ubuntu下安装opencv 2.4.9 脚本,支持摄像头和cuda
查看>>
Tensorflow 线性回归预测房价实例
查看>>
UBUNTU tftp 配置
查看>>
利用runtime给系统类添加动态属性
查看>>
通讯录管理系统(C语言)
查看>>
PHP类与继承
查看>>
Proxifier突破代理服务器上网的限制
查看>>
Oracle(ERROR SP2-0642)
查看>>
反射加强(一)
查看>>
The class has no identifier property
查看>>
碰到的一些面试问题
查看>>
APICloud框架——总结一下最近开发APP遇到的一些问题 (二)
查看>>
python day04
查看>>