博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
1.1(Spring学习笔记)Spring-事务基础
阅读量:7041 次
发布时间:2019-06-28

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

一、Spring 事务

  Spring提供对事务支持的核心包是spring-tx-4.3.6.RELEASE包。

  该包类有三个核心接口,提供对事务的支持:

 

  1.1PlatformTransactionManager

  该接口是Spring提供的平台管理器,主要用于事务管理。

  该接口提供了如下方法:

  TranscationStatus getTransaction(TransactionDefinition definition);用于获取事务状态信息。

  void commit(TransactionStatus status):提交事务

  void rollback(TransactionStatus status):事务回滚

  此接口的具体实现类:

  org.springframework.jdbc.datasource.DataSourceTransactionManager(用于配置JDBC)。

 

  1.2TransactionDefinition

  TransactionDefinition是事务定义的对象,包含定义事务规则,获取事务信息等操作。

  String getName();获取事务对象名称。

  int getLsolationLeve();获取事务隔离级别。

  int getPropagationBehavior();获取事务传播行为。

  int getTimeout();获取事务超时时间。

  boolean isReadOnly()判断事务是否只读。

  

  1.3TransactionStatus

  TransactionStatus是事务的状态,包含方法:

  void flush();刷新事务

  boolean isCompleted();判断事务是否完成。

  boolean isNewTranscation();判断是否为新事务。

  boolean isRollbackOnly();判断事务是否回滚。

  void setRollbackOnly:设置事务回滚。

 

二、声明式事务管理

  声明式事务管理式通过AOP将事务管理作为一个切面,然后将切面(事务管理)织入目标类中。

 

  先看一个失败案例,未配置事务,进行数据库操作失败情况:

  Account.java

public class Account {    private Integer id;    private String username;    private Double balance;        public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public Double getBalance() {        return balance;    }    public void setBalance(Double balance) {        this.balance = balance;    }        @Override    public String toString() {        return "Account [id=" + id + ", username=" + username + ", balance=" + balance + "]";    }    }

 

AccountDao.java(定义数据库相关操作)

import java.util.List;public interface AccountDao {    public int addAccount(Account account);    public int updateAccount(Account account);    public int deleteAccount(int id);    public Account findAccountById(int id);    public List
findAllAccounts(); public void transfer(String outUser, String inUser, Double money);//转账}

 

AccountDaoImpl.java (AccountDao的实现类)

import java.util.List;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.RowMapper;public class AccountDaoImpl implements AccountDao{    private JdbcTemplate jt;        public void setJt(JdbcTemplate jt) {        this.jt = jt;    }    @Override //添加用户    public int addAccount(Account account) {        String sql = "insert into account(username,balance) value(?,?)";        Object[] obj = new Object[] {            account.getUsername(),            account.getBalance()        };        int num = jt.update(sql,obj);        return num;    }    @Override   //更新用户    public int updateAccount(Account account) {        String sql = "update account set username=?,balance=?,where id = ?";        Object[] obj = new Object[] {                account.getUsername(),                account.getBalance(),                account.getId()        };        int num = jt.update(sql,obj);        return num;    }    @Override  //删除用户    public int deleteAccount(int id) {        String sql = "delete from account where id = ?";        int num = jt.update(sql,id);        return num;    }    @Override  //按ID查找    public Account findAccountById(int id) {        String sql = "select * from account where id = ?";        //设置映射,即表中一行记录对应一个Accout对象(数据库中列名要和对象属性名一致)        RowMapper
rp = new BeanPropertyRowMapper
(Account.class); return this.jt.queryForObject(sql, rp, id); } @Override//查找所有对象 public List
findAllAccounts() { String sql = "select * from account"; RowMapper
rp = new BeanPropertyRowMapper
(Account.class); return this.jt.query(sql,rp); } @Override //转账 public void transfer(String outUser, String inUser, Double money) { //转账 this.jt.update("update account set balance = balance - ?" + "where username = ?", money, outUser); int i = 1/0; //模拟意外情况。 //收账 this.jt.update("update account set balance = balance + ?" + "where username = ?",money,inUser); }}

 

 beans.xml

 

测试:

  

import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.jdbc.core.JdbcTemplate;public class JDBCTemplateTest {    public static void main(String[] args) {        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");        AccountDao accountDao = (AccountDao)ac.getBean("accountDao");        Account hcf = new Account();        Account zrx = new Account();        //设置两个用户        hcf.setUsername("hcf");        hcf.setBalance(1000.0);            zrx.setUsername("zrx");        zrx.setBalance(1000.0);        //将用户添加到数据库        accountDao.addAccount(hcf);        accountDao.addAccount(zrx);        //zrx向hcf转账500        accountDao.transfer("zrx", "hcf", 500.0);        System.out.println("成功");    }}

 

 

 

 转账方法中人为添加一个错误,诸侯出现了转账的金额扣除了,但是收账方没有收到金额。

这种情况显然是我们不允许的。

 

这时就可以通过事务来实现,把转账功能作为一个事务。

即使中途出现错误没有将钱转给收账方,会发生回滚转账方的钱也不会扣除。

 

  

  2.1基于XML的声明式事务

  首先我们需要如下jar包:

  

 

  先了解下xml中配置事务的元素:

  <tx:advice>配置事务通知,

  属性transaction-manager:指定事务管理器。

 

    <tx:attributes>:<tx:advice>的子元素,用于配置事务细节。

 

      <tx:method>:<tx:attributes>的子元素,用于配置会务相关信息。

      属性:name:指定与事务关联的方法,可采用通配符*。

         propagation:指定事务传播行为。

         isolation;指定事务隔离级别,默认为REFAULT。

         read-only:指定事务是否只读。

  

  我们只需在benas.xml中配置事务相关信息,然后通过切面的配置,将目标方法织入即可。

 

在xml中添加事务配置,我们再来进行转账操作。

 

import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import org.springframework.jdbc.core.JdbcTemplate;public class JDBCTemplateTest {    public static void main(String[] args) {        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");        AccountDao accountDao = (AccountDao)ac.getBean("accountDao");        Account hcf = new Account();        Account zrx = new Account();                //zrx向hcf转账500        accountDao.transfer("zrx", "hcf", 500.0);        System.out.println("成功");    }}

再次运行出现错误后数据库中的balance并没有被扣除。

转账和收账作为一个整体,一荣俱荣,一损俱损。

 

  2.2基于Annotation的声明式事务

    1)在xml中配置事务注解驱动

    <tx:annotation-driven transaction-manager="transactionManager"/>

    2)在需要使用事务的类(对类中所有方法有效)或方法(只对方法有效)上添加@Transactional注解。

    

   @Transactional注解属性:

   transactionManager:指定事务管理器。

   isolation:指定事务隔离级。

   noRollbackFor:用于指定遇到异常时强制不执行回滚。

   noRollbackForClassName:指定遇到多个异常时强制不执行回滚。

   该属性可指定多个异常类名。

   propagation:指定事务传播行为。

   read-only:设置事务是否只读,默认为false。

   rollbackFor:用于指定遇到特定异常时强制发生回滚。

   rollbackForClassName:指定遇到多个异常时强制执行回滚。

   timeout:指定事务超时时长。

 

  beans.xml

  

 

将转账方法加上注解:

@Override //转账    @Transactional(propagation = Propagation.REQUIRED,                   isolation = Isolation.DEFAULT, readOnly = false)    public void transfer(String outUser, String inUser, Double money) {        //转账        this.jt.update("update account set balance = balance - ?" +                        "where username = ?", money, outUser);        int i = 1/0;  //模拟意外情况。        //收账        this.jt.update("update account set balance = balance + ?" +                        "where username = ?",money,inUser);    }

 

   

转载于:https://www.cnblogs.com/huang-changfan/p/10446932.html

你可能感兴趣的文章
openstack 云服务上创建的虚拟机,主机名修改
查看>>
css3 贝塞尔曲线cubic-bezier(x1, y1, x2, y2)
查看>>
远程连接docker daemon,Docker Remote API
查看>>
C语言dll文件的说明以及生成、使用方法
查看>>
.NET零基础入门05:委托与事件
查看>>
【阿里云MVP公益共创项目】服务数万爱心教师支教,推动中国渔业生态保护
查看>>
Linux命令复习和练习_03
查看>>
使用 github pages, 快速部署你的静态网页
查看>>
react 之 state 对象
查看>>
Java中的锁原理、锁优化、CAS、AQS
查看>>
“智能厨电+渠道精耕”,华帝迈出“关键一步”
查看>>
Scrapy爬虫(2)爬取新浪旅游图片
查看>>
Nginx反向代理以及负载均衡配置
查看>>
巨头抢滩视频云 金山云稳坐头把交椅
查看>>
索尼富士康领投,AR显示技术厂商Digilens获得2200万美元融资
查看>>
Qt5 GUI 开发的应用易受远程代码执行漏洞的影响
查看>>
搞懂Java动态代理
查看>>
NTKO使用说明
查看>>
django实现目录上传(最简单的方法)
查看>>
用update和replace在sql中替换某一个字段的部分内容
查看>>