• Java开启事务操作数据库


    一、事务的四大特性(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

  • 相关阅读:
    [PHP] laravel框架注意bootstrap/cache
    [git] git拉取远程分支代码
    Prometheus监控系统(4)pushgateway及自定义脚本
    k8s 学习
    pxc /Galera Cluster详解
    Percona Monitoring and Management
    etcd获取所有key
    kubernetes Pod驱逐迁移drain用法
    kubernetes etcd数据管理
    办公环境下k8s网络互通方案
  • 原文地址:https://www.cnblogs.com/hyl-home/p/7365035.html
Copyright © 2020-2023  润新知