spring mysql处理脏读_使用Spring框架实现数据库事务处理

企业级应用系统在更新数据库数据时,一般都采用数据库事务处理,以确保数据库数据的一致性。本文主要讨论在Spring框架中如何使用数据库事务处理更新数据库数据。通过本课的学习,可以达到如下目标。

● 了解JDBC对数据库事务处理的支持

● 掌握在Spring框架中使用事务处理的技术

事务处理对数据库来说,是对数据库的一系列SQL语句操作,这些操作被组织为一个事务。事务具有原子性,即事物中的操作要么全部执行,要么全部不执行。若事务中的SQL语句在执行过程中发生错误,事务需要对已经执行的SQL语句进行回滚操作,撤销先前对数据库的操作,防止数据库出现错误状态。

例如,在课程案例mooc数据库中,一个业务是学生购买课程,购买课程业务步骤包括更新teacher表,记录老师的收入,同时student_course表增加一条购买记录,更新student表的余额字段。上述业务步骤需要全部执行完毕,才能反映出学生购买课程的正确状态。如果因意外情况,上述操作仅成功执行了部分SQL语句,其它语句没有执行或执行失败,就会造成学生购买课程这个业务记录不完整,数据库处于数据错乱状态。若利用数据库事务技术执行上述操作,当发生上述情况时,数据库系统会将先前执行的SQL语句撤销,将数据库回滚到事务执行前状态。

1、JDBC对数据库事务处理的支持

JDBC本身就提供了对数据库事务处理的支持,使用java.sql.Connection对象完成事务的提交。使用Connection提交数据库事务处理代码如下。

bee9dbec33e52a74d77dc8a5c120653f.png

Connection类的setAutoCommit方法用于设置JDBC提交SQL语句的方式。设置为ture时,JDBC自动提交SQL语句,JDBC提交SQL语句的方式默认为true。设置为false时,SQL语句的提交由应用程序负责,应用程序必须调用commit方法,同时要在执行SQL语句异常处理块中调用rollback方法,对异常发生前进行的数据库进行回滚操作。

在企业级应用中,事务一般是并发执行的,当事务并发执行时,就会发生数据库数据同步的问题,具体问题可分为下面四种类型。

(1)脏读:一个数据库事务在更新数据的过程中,数据是保存在内存中的,只有调用commit方法,更新的数据才最终写到数据库中。如果一个事务使用了另一个事务更新但没保存的数据,这个数据就称为脏数据,事务读取这个数据就称为脏读。

(2)不可重复读:在同一事务中,两次读取同一记录,读取的记录内容却不相同。例如,事务A第一次读取了一条记录,同时事务B更新并提交了该条记录,事务A第二次读取该条记录时,当前读取的记录内容和第一次读取的记录内容不相同。

(3)幻读:当事务A对表中的所有记录进行了修改,同时事务B又在表中插入了一条新的记录。A事务在后续对该表操作时,就会发现表中还存在没有修改的记录,就好象发生了幻觉一样。

(4)丢失更新:当事务A和事务B对同一数据进行修改时,就会发生丢失更新的问题。例如,B事务对m记录进行了修改,A事务在修改m记录时发生异常并回滚,就会将B事务对m记录的修改覆盖掉。

为了解决上面提到的事务并发问题,JDBC定义了五种事务隔离级别来解决来解决这些并发导致的问题。

表1 JDBC提供的事务隔离级别说明

d21722193fe06ef93c4005a3259a96c2.png

表中隔离级别从上到下依次增高,最高级别是TRANSACTION_SERIALIZABLE,它通过强制事务串行执行(不是并行),避免了事务并发执行导致发生的数据同步问题。出于应用程序访问数据库性能的考虑,一般设置隔离级别为TRANSACTION_READ_COMMITTED。

2、在Spring框架中调用事务处理

下面给出具体执行事务处理的案例程序。案例程序的数据源采用mooc数据库,mooc数据库的结构以及本案例中没有列出的代码详见《Spring使用JDBC访问MySQL数据库》一文。

让Spring框架开始执行一个数据库事务时,需要分成三步走。第一步配置数据源DataSource;第二步声明事务管理TransactionManager类;第三步定义可以执行事务的DAO类。

第一步:配置数据源DataSource

需要让Spring框架知道数据库的位置及其连接方式,这个工作由DataSource完成。Spring框架通过DataSource连接数据库,DataSource既可以在Spring框架的配置文件中配置,也可以放在Bean类中配置。下面是在Spring配置文件中配置数据源的代码。

89c070dded05fad74af22a844fd70616.png

配置语句定义了MySQL数据库的URL地址、访问账户及访问密码。

第二步:声明事务管理TransactionManager

Spring 框架提供了PlatformTransactionManager作为事务管理类的顶层接口,声明了初始化事务、提交事务、回滚事务等接口。接口实现由具体的数据库驱动类实现。具体包括DataSourceTransactionManager、HibernateTransactionManager等实现类。本文主要用DataSourceTransactionManager来实现事务的管理。在Spring框架配置文件中配置DataSourceTransactionManager类。

8c52cb75a5dba9ccf607a7180791839a.png

声明DataSourceTransactionManager类,需要传入之前已声明的DataSource数据源。

第三步:定义可以执行事务的DAO类

DAO提供了应用程序访问数据源必要的接口和方法,接口和方法的具体实现细节,程序并不需要了解。DAO的具体细节详见《Spring使用JDBC访问MySQL数据库》一文。

f52fa82dd9f4890c784e3fda6dbd8ee1.png

CourseTransactio类实现了CourseDao接口,CourseDao是访问mooc数据库的顶层接口,接口提供了mooc数据库表的增删改查操作。CourseTransactio主要实现了CourseDao类的buyCourse,实现学生购买课程事务。购买课程事务涉及到更新teacher表,在student_course表增加一条购买记录,更新student表的余额字段数据库操作,这些操作需要进行连续处理,中间不能中断出错,如果出错则需要做回滚处理。 因此,buyCourse方法采用数据库事务进行处理。

事务处理从TransactionDefinition开始,前面我们谈到了事务的隔离级别,TransactionDefinition就是用来定义事务隔离级别的。DefaultTransactionDefinition表示使用数据库的默认隔离级别,对大部分数据库而言,默认隔离级别是TRANSACTION_READ_COMMITTED。

当TransactionDefinition 创建后,可以通过调用 getTransaction方法开始事务,该方法会返回 TransactionStatus 的一个实例。 TransactionStatus 用于追踪当前的事务状态,如果后面的SQL语句都运行成功,可以使用 TransactionManager 的 commit() 方法来提交这个事务,否则使用 rollback() 方法来回滚整个操作。

完整的配置文件代码。

79f5b830a40867771a980893f13f3216.png

学生实体类代码。

9500485fe323c159411328ab158bd444.png

老师实体类代码。

37037bf90e9cfd5d5b09df3e545723fa.png

student表映射到学生实体类。

c7fd87ec6c7bd5579cee103d4b458aa0.png

teacher表映射到老师实体类。

81893817a450750a1a21e5fea9ab0f4a.png

测试类代码。

612409a5662979a4051ecb10bebaf1dd.png

课程小结

(1)事务处理对数据库来说,是对数据库的一系列SQL语句操作,这些操作被组织为一个事务。事务具有原子性,即事物中的操作要么全部执行,要么全部不执行。若事务中的SQL语句在执行过程中发生错误时,事务需要对已经执行的SQL语句进行回滚操作,撤销先前对数据库的操作,防止数据库出现错误状态。

(2)让Spring框架开始执行一个数据库事务时,需要分成三步走。第一步配置数据源DataSource;第二步声明事务管理TransactionManager类;第三步定义可以执行事务的DAO类。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值