一、事务管理

一个数据库事务是一个被视为单一的工作单元操作序列。

事务管理有四个原则,被成为ACID

  • Atomicity 原子性—— 事务作为独立单元进行操作,整个序列是一体的,操作全都成功或失败。
  • Consistency 一致性—— 引用完整性的一致性,表中唯一的主键等。
  • Isolation 隔离性—— 每个事务同时处理时,事务之间不会干预
  • Durability 持久性 事务一旦完成,结果是不可逆的,不会因为故障而失效

那么一个关系型数据库将保证事务有这四个原则。

使用SQL发布到数据库中的事务简单视图如下:

  • 使用begin transaction命令开始事务
  • 使用SQL查询语句执行更新操作
  • 如果操作都成功,则提交操作,否则回滚操作

Spring 事务支持

  • Spring框架在不同底层事务管理API的顶部提供了一个抽象层。
  • Spring事务支持主要通过添加事务能力到POJO来提供EJB事务。
  • Spring支持编程式和声明式事务管理。
  • EJB需要一个应用程序服务器,但Spring事务管理可以不需要应用程序服务器。

全局事务与局部事务

  • 局部事务?

它是一个特定单一事务资源,例如一个JDBC连接。

若你的生产环境是集中的,该环境中的程序组件和资源位于一个位置,而事务管理只涉及到一个运行
单一机器中的本地数据管理器,则适用局部事务。

  • 全局事务?

它可以跨多个事务资源,如一个分布式系统中的事务。

若你的生产环境是分散的,所有资源分布在多个系统中,则需要局部事务和全局事务管理。
分布式或全局事务跨多个系统执行,它的执行需要全局事务管理系统和所有相关系统的局部数据管理人员之间的协调。

编程式与声明式事务管理

  • 编程式事务管理: 用编程的方式进行事务管理,灵活性较高,但维护性差。
  • 声明式事务管理: 从业务代码中分离事务管理,仅使用注释或XML配置来管理事务。

声明式事务管理比编程式事务管理更适合,它可以使用AOP方法进行模块化,Spring AOP框架也可以用来进行声明式事务管理。

Spring事务抽象

Spring事务管理的五大属性:隔离级别传播行为只读属性事务超时回滚规则

隔离级别

  • 默认: TransactionDefinition.ISOLATION_DEFAULT
  • 读取提交内容: TransactionDefinition.ISOLATION_READ_COMMITTED
    能阻止误读,可发生不可重复读和虚读。
  • 读取未提交内容: TransactionDefinition.ISOLATION_READ_UNCOMMITTED
    可以发生误读、不可重复读和虚读。
  • 可重读内容: TransactionDefinition.ISOLATION_REPEATABLE_READ
    表明能够阻止误读和不可重复读;可以发生虚读。
  • 可串行化: TransactionDefinition.ISOLATION_SERIALIZABLE
    表明能够阻止误读、不可重复读和虚读。

传播行为

  • 支持当前事务:
    TransactionDefinition.PROPAGATION_MANDATORY
  • 支持当前事务,在嵌套事务执行:
    TransactionDefinition.PROPAGATION_NESTED
  • 不支持当前事务:
    TransactionDefinition.PROPAGATION_NEVER
  • 不支持当前事务,总是执行非事务性: TransactionDefinition.PROPAGATION_NOT_SUPPORTED
  • 支持当前事务,若不存在则创建新事务:
    TransactionDefinition.PROPAGATION_REQUIRED
  • 创建新事务,将当前事务挂起:
    TransactionDefinition.PROPAGATION_REQUIRES_NEW
  • 支持当前事务,若不存在则执行非事务性:
    TransactionDefinition.PROPAGATION_SUPPORTS
  • 使用默认超时底层事务系统,若不支持超时则没有传播行为:
    TransactionDefinition.TIMEOUT_DEFAULT

事务抽象

Spring事务抽象由org.springframework.transaction.PlatformTransactionManager接口定义。

public interface PlatformTransactionManager{//根据传播行为,返回当前活动事务或创建新事务TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;//提交事务以及事务状态void commit(TransactionStatus status) throws TransactionException;//执行事务回滚void rollback(TransactionStatus status) throws TransactionException;
}

TransactionDefinition接口是Spring事务支持的核心接口,定义如下:

public interface TransactionDefinition{int getPropagationBehavior(); //获取传播行为int getIsolationLevel();    //获取隔离级别String getName(); //获取事务名称int getTimeout(); //获取事务超时时间boolean isReadOnly(); //获取只读属性
}

TransactionStatus接口为事务代码提供简单方法来控制事务执行和查询事务状态。

public interface TransactionStatus extends SavepointManager{boolean isNewTransaction();  //是否为新事务boolean hasSavepoint(); //该事务内部是否有一个保存点,也就是说,基于一个保存点已经创建了嵌套事务。void setRollbackOnly(); //该方法设置该事务为 rollback-only 标记。boolean isRollbackOnly();  //该事务是否已标记为 rollback-only。boolean isCompleted();    //事务是否已经提交或回滚。
}

二、编程式事务管理

我们尝试一下如何进行编程式事务管理。
步骤一:添加依赖包

  • jdbc.jar
  • mysql-connector.jar
  • transaction.jar

pom.xml

     <dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>5.3.23</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>5.3.24</version></dependency>

步骤二:创建POJO类

User.java

public class User{private Integer id;private String name;private Integer age;private Integer marks;private Integer year;private Integer sid;public User() {}public User(Integer id, String name, Integer age) {this.id = id;this.name = name;this.age = age;}public User(Integer id, String name, Integer age, Integer marks, Integer year, Integer sid) {this.id = id;this.name = name;this.age = age;this.marks = marks;this.year = year;this.sid = sid;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Integer getMarks() {return marks;}public void setMarks(Integer marks) {this.marks = marks;}public Integer getYear() {return year;}public void setYear(Integer year) {this.year = year;}public Integer getSid() {return sid;}public void setSid(Integer sid) {this.sid = sid;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", age=" + age +", marks=" + marks +", year=" + year +", sid=" + sid +'}';}
}

步骤三:创建dao层

UserDao.java

public interface UserDao {public void setDataSource(DataSource ds);public void create(String name,Integer age,Integer marks,Integer year);public List<User> listUsers();
}

步骤四:创建Mapper层

UserMapper.java

public class UserMapper implements RowMapper<User> {@Overridepublic User mapRow(ResultSet rs, int rowNum) throws SQLException {return new User(rs.getInt("id"),rs.getString("name"),rs.getInt("age"), rs.getInt("marks"),rs.getInt("year"),rs.getInt("sid"));}
}

步骤五:创建Template层

UserJdbcTemplate.java

public class UserJdbcTemplate implements UserDao {private DataSource dataSource;private JdbcTemplate jdbcTemplate;private PlatformTransactionManager platform;private String sql;public void setPlatform(PlatformTransactionManager platform) {this.platform = platform;}@Overridepublic void setDataSource(DataSource ds) {this.dataSource = ds;this.jdbcTemplate = new JdbcTemplate(dataSource);}@Overridepublic void create(String name, Integer age, Integer marks, Integer year) {TransactionDefinition definition = new DefaultTransactionDefinition();TransactionStatus status = platform.getTransaction(definition);try {sql = "insert into user (name,age) values(?,?)";jdbcTemplate.update(sql,name,age);sql = "select max(id) from user";int sid = jdbcTemplate.queryForInt(sql,null,Integer.class);sql = "insert into marks(sid,marks,year) values (?,?,?)";jdbcTemplate.update(sql,sid,marks,year);System.out.println("提交");platform.commit(status);}catch (DataAccessException e){System.out.println("Error in creating record,rolling back");platform.rollback(status);throw e;}return;}@Overridepublic List<User> listUsers() {sql = "select * from user u,marks m where u.id = m.sid";return jdbcTemplate.query(sql,new UserMapper());}}

步骤六:bean配置

jdbc.xml

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/><property name="username" value="root"/><property name="password" value="123456"/></bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource" /></bean><bean id="userJDBCTemplate" class="org.example.Template.UserJdbcTemplate"><property name="dataSource" ref="dataSource" /><property name="platform" ref="transactionManager" /></bean>

输出结果

回滚事件:

------Records creation--------
Error in creating record,rolling back
Exception in thread "main" org.springframework.jdbc.BadSqlGrammarException: StatementCallback; bad SQL grammar [select max(id) form user]; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'user' at line 1at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:239)at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70)at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1541)at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:393)at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:465)at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:475)at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:508)at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:515)at org.example.Template.UserJdbcTemplate.create(UserJdbcTemplate.java:46)at org.example.Main.main(Main.java:26)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'user' at line 1at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:423)at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)at com.mysql.jdbc.Util.getInstance(Util.java:408)at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:944)at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3978)at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3914)at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2530)at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2683)at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2491)at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2449)at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1381)at org.springframework.jdbc.core.JdbcTemplate$1QueryStatementCallback.doInStatement(JdbcTemplate.java:452)at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:381)... 6 more

三、声明式事务管理

我们来尝试一下声明式事务管理
这里展示与编程式事务管理的不同的地方。

1、Template类不再有PlatformTransactionManager参与,即正常的JDBC框架内容。
2、配置文件jdbc.xml,声明tx命名空间,aop命名空间,装配事务管理和面向切面配置

jdbc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-3.0.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.0.xsd"><!-- 初始化数据库连接池 --><bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/TEST"/><property name="username" value="root"/><property name="password" value="123456"/></bean>##AOP框架中实际调用的方法<tx:advice id="txAdvice"  transaction-manager="transactionManager">##目标<tx:attributes>##锚定方法<tx:method name="create"/></tx:attributes></tx:advice>##配置aop框架,设置切入点,加载advice<aop:config><aop:pointcut id="createOperation" expression="execution(* com.tutorialspoint.StudentJDBCTemplate.create(..))"/><aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/></aop:config>##初始化事务管理器<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource"  ref="dataSource" />    </bean>#初始化template<bean id="studentJDBCTemplate"  class="com.tutorialspoint.StudentJDBCTemplate"><property name="dataSource"  ref="dataSource" />  </bean></beans>

Spring笔记(9):事务管理ACID相关推荐

  1. 【Spring学习笔记 九】Spring声明式事务管理实现机制

    什么是事务?事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用,关乎数据准确性的地方我们一定要用到事务,防止业务逻辑出错. 什么是事务管理,事务管理对于企业应用而言至 ...

  2. Spring中的事务管理详解

    在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...

  3. Spring(四)——AOP、Spring实现AOP、Spring整合Mybatis、Spring中的事务管理

    文章目录 1. 什么是AOP 2. 使用Spring实现AOP 2.1 使用Spring的API 接口实现 2.2 自定义实现 2.3 使用注解实现 3. 整合MyBatis 3.1 MyBatis- ...

  4. spring事务管理器的作用_【面试必问】Spring中的事务管理详解

    在这里主要介绍Spring对事务管理的一些理论知识,实战方面参考上一篇博文: http://www.cnblogs.com/longshiyVip/p/5061547.html 1. 事务简介: 事务 ...

  5. (转)使用Spring配置文件实现事务管理

    http://blog.csdn.net/yerenyuan_pku/article/details/52886207 前面我们讲解了使用Spring注解方式来管理事务,现在我们就来学习使用Sprin ...

  6. Spring配置文件详解三:Spring声明式事务管理

    1.声明式事务管理 Spring提供了声明式事务管理,这是通过Spring AOP实现的. 原理:Spring中进行事务管理的通常方式是利用AOP(面向切片编程)的方式,为普通java类封装事务控制, ...

  7. Spring JDBC-Spring对事务管理的支持

    概述 事务管理关键抽象 Spring事务管理的实现类 Spring JDBC 和MybBatis的事务管理器的配置 JPA的事务管理器的配置 Hibernate的事务管理器的配置 JTA 的事务管理器 ...

  8. Spring框架的事务管理及应用

    Spring框架简介 Spring框架是一个2003年2月才出现的开源项目,该开源项目起源自Rod Johnson在2002年末出版的<Expert One-on-One J2EE Design ...

  9. Spring入门5.事务管理机制

    Spring入门5.事务管理机制 20131126 代码下载 : 链接: http://pan.baidu.com/s/1kYc6c 密码: 233t 回顾之前的知识,Spring 最为核心的两个部分 ...

  10. spring声明式事务管理方式( 基于tx和aop名字空间的xml配置+@Transactional注解)

    1. 声明式事务管理分类 声明式事务管理也有两种常用的方式, 一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解. 显然基于注解的方式更简单易用,更清爽. ...

最新文章

  1. 【跟着我们学Golang】之异常处理
  2. Mybaits整合Spring自动扫描 接口,Mybaits配置文件.xml文件和Dao实体类
  3. 当打开淘宝的那一刻,它就知道你想要的是什么
  4. unity3d的执行顺序
  5. 侧边栏_第四课 侧边栏和过滤器
  6. linux远程登录模拟输入输出重定向,从零开始学习Linux(三十三):Shell基础之输入输出重定向...
  7. onnx格式转tensorRT
  8. fabricjs上手指南
  9. 建议考前多熟记的知识点(1)-(3)《系统集成项目管理工程师软考辅导》
  10. SpringBoot 添加junit单元测试+Spring Boot 的测试类库
  11. 时钟偏移(Skew)和时钟抖动(Jitter)
  12. 分子动力学模拟软件VMD的安装与使用
  13. 基于SSM实现图书借阅管理系统-毕业设计
  14. NYOJ -1364 (第十一届河南省赛)
  15. 微波反应试验温度、时间、压力及功率控制
  16. 梦幻西游手游服务器维护时间,梦幻西游手游5.11维护公告
  17. 免费个人网页制作指南Dreamweaver教程
  18. 历届真题 杨辉三角形【第十二届】【省赛】【B组】
  19. 免激活Vista并合法使用1年的方法
  20. 计算机网络安全所学知识大纲,计算机网络安全课程教学大纲.doc

热门文章

  1. Stearic acid-mPEG,mPEG-STA,甲氧基PEG-单硬脂酸,具有优异疏水性
  2. JAVA英雄血战代码,骑士助手版英雄血战下载
  3. [转]ASP.NET MVC3 + EF 性能优化解决方案以及最优架构
  4. 陈春花:一定要让顶上的人有末位淘汰,让基层活不好是错的
  5. 胃肠功能紊乱有哪些表现?这3种症状说明你已中招!
  6. 拓扑排序 Codeforces Round #748 (Div. 3)E. Gardener and Tree
  7. Cocoapod集成阿里百川电商SDK 常见问题 解决方案
  8. 新浪微博搜索结果数据抓取
  9. 如何使用POI导出excel表格,以及处理浏览器无法识别下载文件的问题
  10. 《青年中国说》观后感