Java开启事务操作数据库

摘要:
1、 事务(ACID)的四个特征1.原子性:组成事务的语句构成一个逻辑单元,不能只执行其中的一部分;2.一致性:事务执行前后,数据库与理论值一致(数据库完整性约束);3.隔离:一个事务和另一个事务互不影响;4.持久性:事务处理的效果可以永久保存。2、 隔离级别1.多线程并发执行可以

一、事务的四大特性(ACID)

1、原子性(atomicity):组成事务的语句形成了一个逻辑单元,不能只执行一部分;

2、一致性(consistency):在事务处理执行前后,数据库与理论值是一致的(数据库完整性约束);

3、隔离性(isolcation):一个事务处理和另一个事务处理相互间互不影响;

4、持续性(durability):事务处理的效果能够被永久保存下来。

二、隔离级别

1、多线程并发执行可能会产生以下三个问题:

  脏读(dirtyreads):一个事务读取了另一个事务未提交的并行事务写的数据;

  不可重复读(non-repeatablereads):一个事务重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务修改过;

  幻读(phantomread):一个事务重新执行一个查询,返回一套符合条件的行,发现这些行因为最近提交的事务而发生了改变

2、隔离级别

  读未提交(Read uncommitted):未解决

  读已提交 (Readcommitted):已解决:脏读

  可重复读 (Repeatableread):已解决:脏读,不可重复读

  序列化 (Serializble):已解决:脏读,不可重复读,幻读

3、设置隔离级别

  connection.setTransactionlsolation(Connection.事务级别)

  MySql默认为度已提交;

三、基本操作

1、connection.setAutCommit(false):关闭事务自动提交

2、connection.commit():手动提交事务

3、connection.rollback():事务回滚

补:撤销事务中的部分操作

SavePoint sp = connection.setSavepoint();:设置事务回滚点

connection.rollback(sp);

connection.commit();:最后不要忘了提交事务,否则前面需要提交保存的操作也将不会保存到数据库中

代码示例:(修改学生并更新班级)

StudentDao.java:

 1 public void updateStudent(Connection conn,Student s) throws SQLException{
 2         String sql = "update student set name = ?,age = ?,sex = ?,clazzid = ? where id = ?";
 3         try {
 4             st = conn.prepareStatement(sql);
 5             st.setString(1, s.getName());
 6             st.setInt(2, s.getAge());
 7             st.setString(3, s.getSex());
 8             st.setInt(4, s.getClazz().getId());
 9             st.setInt(5, s.getId());
10         } catch (SQLException e) {
11             e.printStackTrace();
12         }
13         /*上面只捕获st = conn.prepareStatement(sql);的异常
14          * st.executeUpdate();最后将执行对数据库更改的操作产生的异常抛出到上一层(Service)调用者
15          * connection开启事务在Service中开启
16          * 所以Connection来自Service中开启事务的连接
17         */
18         st.executeUpdate();
19     }

ClazzDao.java:

 1 //为学生所转到的新班级增加一个人数
 2     public void addClazzCount(Connection conn,int clazzid) throws SQLException{
 3         String sql = "update clazz set count = count + 1 where id =?";
 4         try {
 5             st = conn.prepareStatement(sql);
 6             st.setInt(1, clazzid);
 7         } catch (SQLException e) {
 8             e.printStackTrace();
 9         }
10         /*上面只捕获st = conn.prepareStatement(sql);的异常
11          * st.executeUpdate();最后将执行对数据库更改的操作产生的异常抛出到上一层(Service)调用者
12          * connection开启事务在Service中开启
13          * 所以Connection来自Service中开启事务的连接
14         */
15         st.executeUpdate();
16     }
17     //为学生原来所在的班级减少一个人数
18     public void subClazzCount(Connection conn,int clazzid) throws SQLException{
19         String sql = "update clazz set count = count -1 where id =?";
20         try {
21             st = conn.prepareStatement(sql);
22             st.setInt(1, clazzid);
23         } catch (SQLException e) {
24             e.printStackTrace();
25         }
26         /*上面只捕获st = conn.prepareStatement(sql);的异常
27          * st.executeUpdate();最后将执行对数据库更改的操作产生的异常抛出到上一层(Service)调用者
28          * connection开启事务在Service中开启
29          * 所以Connection来自Service中开启事务的连接
30         */
31         st.executeUpdate();
32     }

重点来了!

Service中开启,提交,回滚事务

Service.java

 1     //更新学生信息
 2     public void update(Student s) {
 3         Connection connection = JDBCUtil_C3P0.getConnection();
 4         try {
 5             //关闭事务自动提交(开启事务)
 6             connection.setAutoCommit(false);
 7             //在数据库中查找学生原本所在班级
 8             int oldclazzid = studentDao.findById(s.getId()).getClazz().getId();
 9             //如果学生班级发生改变,对班级表进行修改
10             if(oldclazzid !=s.getClazz().getId()){
11                 //为转到的新班级增加一个学生
12                 clazzDao.addClazzCount(connection, s.getClazz().getId());
13                 //为原本所在的旧班级减少一个学生
14                 clazzDao.subClazzCount(connection, oldclazzid);
15                 //测试事务,手动抛出一个SQL异常
16                 //throw new SQLException("操作异常");
17             }
18             //修改学生信息
19             studentDao.updateStudent(connection, s);
20             //以上所有操作无异常则提交事务
21             connection.commit();
22             
23         } catch (SQLException e) {
24             e.printStackTrace();
25             //一旦事务中有哪一步操作发生异常则进行事务回滚
26             try {
27                 connection.rollback();
28             } catch (SQLException e1) {
29                 e1.printStackTrace();
30             }
31         }finally{
32             //关闭连接资源
33             clazzDao.close(connection);
34             studentDao.close(connection);
35         }
36         
37     }

Over

免责声明:文章转载自《Java开启事务操作数据库》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇chrome浏览器下JavaScript实现clipboard时无法访问剪切板解决方案【微信小程序】在swiper-item使用wx:for时出现的问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MySQL死锁

https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlocks.html 什么是mysql的死锁? A deadlock is a situation where different transactions are unable to proceed because each holds a lock t...

Hibernate 缓存机制

一、why(为什么要用Hibernate缓存?) Hibernate是一个持久层框架,经常访问物理数据库。 为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。 缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。 二、what(Hibernate缓存原理是怎样的?)Hi...

浅谈“微服务”

微服务概述 1.1 易于扩展 1.2 部署简单 1.3 技术异构性 数据库的服务化切分 2.1 什么是“分库分表”? 2.2 数据库扩展的几种方式 2.3 分库分表的几种方式 2.4 引入分库分表中间件后面临的问题 2.5 现有分库分表中间件的横向对比 微服务架构中的分布式事务 3.1 什么是事务? 3.2 事务的四大特性 ACID 3.3 事...

Java高并发,如何解决,什么方式解决

  对于我们开发的网站,如果网站的访问量非常大的话,那么我们就需要考虑相关的并发访问问题了。而并发问题是绝大部分的程序员头疼的问题,但话又说回来了,既然逃避不掉, 那我们就坦然面对吧~今天就让我们一起来研究一下常见的并发和同步吧。   为了更好的理解并发和同步,我们需要先明白两个重要的概念:同步和异步    1、同步和异步的区别和联系    所谓同步,可以...

支付宝 分布式事务服务 DTS三-copy

典型场景和实现原理首先来看一个典型的分布式事务场景 在这个例子中,app1 作为分布式事务的发起方调用了参与者 app2 的 insert 操作和 app3 的 update 操作,之后调用自己的本地 insert 操作,在这个分布式事务中包含了 3 次对 db 的操作,而 3 个 db 分属于不同的系统,图中虚线覆盖的范围是 app1 的一个本地事务模版...

[从源码学设计] Flume 之 memory channel

[从源码学设计] Flume 之 memory channel 目录 [从源码学设计] Flume 之 memory channel 0x00 摘要 0x01 业务范畴 1.1 用途和特点 1.2 Channel 1.3 研究重点 1.4 实际能够学到什么 1.5 总述 0x02 定义 2.1 接口 2.2 配置参数2.2.1 channe...