java积累——数据库手动控制事务工具类

简介: java积累——数据库手动控制事务工具类

引言


在项目中对数据库操作的时候保证事务的完整性是非常重要的,尤其是一个功能中需要对数据库多次操作的时候更是需要小心,其实简单的说:只要保证多次操作使用一个Connection就可以使他们在一个事务中,但是数据库jdbc默认在执行完executeQuery、executeUpdate等方法以后会自动提交事务,这样我们多次操作的时候就不能保证事务的完整性,所以需要我们手动控制事务的提交和回滚操作,下面提供一个帮助类。


package com.bjpowernode.drp.util;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * 
 * @author zhenghao
 *
 */
public class DbUtil {
  public static Connection getConnection(){
    /*Connection conn=null;
    try {
      Class.forName("oracle.jdbc.driver.OracleDriver");
      String url="jdbc:oracle:thin:@127.0.0.1:1521:databaseName";
      String username="userName";
      String password="password";
      try {
        conn=DriverManager.getConnection(url, username, password);
      } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return conn;*/
    Connection conn=null;
    try {
      JdbcConfig jdbcConfig=XmlConfigReader.getInstance().getJdbcConfig();      
      Class.forName(jdbcConfig.getDriverName());
      try {
        conn=DriverManager.getConnection(jdbcConfig.getUrl(), jdbcConfig.getUserName(), jdbcConfig.getPassword());
      } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    } catch (ClassNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return conn;
  }
  public static void close(Connection conn){
    if (conn!=null) {
      try {
        conn.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
  public static void close(Statement statement){
    if (statement!=null) {
      try {
        statement.close();
      } catch (SQLException e) {
        e.printStackTrace();
      } 
    }
  }
  public static void close(ResultSet rs) {
    if(rs!=null){
      try {
        rs.close();
      } catch (SQLException e) {
        e.printStackTrace();
      }
    }
  }
  public static void beginTransaction(Connection conn){
    if (conn!=null) {
      try {
        if(conn.getAutoCommit()){
          conn.setAutoCommit(false);
        }
      } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }
  }
  public static void commitTransaction(Connection conn){
    try {
      if(conn!=null){
        if (!conn.getAutoCommit()) {
          conn.commit();
        }
      }
    } catch (Exception e) {
      // TODO: handle exception
    }
  }
  public static void rollbackTransaction (Connection conn) {
    try {
      if(conn!=null){
        if (!conn.getAutoCommit()) {
          conn.rollback();
        }
      }
    } catch (Exception e) {
      // TODO: handle exception
    }
  }
  public static void resetTransaction(Connection conn){
    try {
      if(conn!=null){
        if (conn.getAutoCommit()) {
          conn.setAutoCommit(false);
        }else{
          conn.setAutoCommit(true);
        }
      }
    } catch (Exception e) {
      // TODO: handle exception
    }
  }
}

上面的工具类中提供了数据库的连接操作;手动开启事务、提交事务、事务回滚、恢复事务状态;关闭Connection ;关闭Statement;关闭ResultSet等等操作,这样在和数据库打交道的时候会方便很多。


手动控制事务示例演示


当我们添加一个节点以后,需要判断这个节点是不是叶子(是有有子节点)而改变is_leaf这个字段的值;


public void addClientOrRegion(Client clientOrRegion) {
    StringBuffer sbSql = new StringBuffer();
    sbSql.append("insert into t_client ( ")
        .append("id, pid, client_level_id, ")
        .append("name, client_id, bank_acct_no, ")
        .append("contact_tel, address, zip_code, ")
        .append("is_leaf, is_client) ")
        .append("values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ");
    Connection conn = null;
    PreparedStatement pstmt = null;
    try {
      conn = DbUtil.getConnection();
      pstmt = conn.prepareStatement(sbSql.toString());
      <strong><span style="color:#ff0000;">DbUtil.beginTransaction(conn);</span></strong>
      // 根据表明获得id,利用id生成器
      pstmt.setInt(1, IdGenerator.generate("t_client"));
      pstmt.setInt(2, clientOrRegion.getPid());
      pstmt.setString(3, clientOrRegion.getClientLevel().getId());
      pstmt.setString(4, clientOrRegion.getName());
      pstmt.setString(5, clientOrRegion.getClientId());
      pstmt.setString(6, clientOrRegion.getBankAcctNo());
      pstmt.setString(7, clientOrRegion.getContactTel());
      pstmt.setString(8, clientOrRegion.getAddress());
      pstmt.setString(9, clientOrRegion.getZipCode());
      pstmt.setString(10, clientOrRegion.getIsLeaf());
      pstmt.setString(11, clientOrRegion.getIsClient());
      pstmt.executeQuery();
      // 根据id查询分销商或者区域,确定是否为叶子
      Client client = findClientOrRegionById(clientOrRegion.getPid());
      if (Constants.YES.equals(client.getIsLeaf())) {
        // 如果非叶子 应该改为叶子
        modifyIsLeafField(conn, clientOrRegion.getPid(), Constants.NO);
      }
      <strong><span style="color:#ff0000;">DbUtil.commitTransaction(conn);</span></strong>
    } catch (Exception e) {
      // TODO: handle exception
      e.printStackTrace();
      <strong><span style="color:#ff0000;">DbUtil.rollbackTransaction(conn);</span></strong>
    } finally {
      DbUtil.close(pstmt);
      <strong><span style="color:#ff0000;">DbUtil.resetTransaction(conn);</span></strong>
      DbUtil.close(conn);
    }
  }

当我们得到connection以后,调用方法来设置事务的提交为手动提交,这样当我们将两步操作都完成以后自己手动提交,如果遇到错误以后调用方法回滚事务,这样我们就可以事务的完整性。在最后释放资源的时候不要忘记恢复事务的提交状态


小结


事务在数据库中是非常重要的,尤其是项目比较大的时候,如果不能保证事务会给我们带来很大的麻烦有时候甚至是灾难。

目录
相关文章
|
6天前
|
负载均衡 NoSQL 算法
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
这篇文章是关于Java面试中Redis相关问题的笔记,包括Redis事务实现、集群方案、主从复制原理、CAP和BASE理论以及负载均衡算法和类型。
一天五道Java面试题----第十天(简述Redis事务实现--------->负载均衡算法、类型)
|
4天前
|
前端开发 关系型数据库 MySQL
【前端学java】MySQL数据库的本地安装
【8月更文挑战第12天】MySQL数据库的本地安装
20 3
|
5天前
|
SQL 数据库 数据安全/隐私保护
SQL Server数据库Owner导致事务复制log reader job无法启动的解决办法
【8月更文挑战第14天】解决SQL Server事务复制Log Reader作业因数据库所有者问题无法启动的方法:首先验证数据库所有者是否有效并具足够权限;若非,使用`ALTER AUTHORIZATION`更改为有效登录名。其次,确认Log Reader使用的登录名拥有读取事务日志所需的角色权限。还需检查复制配置是否准确无误,并验证Log Reader代理的连接信息及参数。重启SQL Server Agent服务或手动启动Log Reader作业亦可能解决问题。最后,审查SQL Server错误日志及Windows事件查看器以获取更多线索。
|
5天前
|
Java 数据库连接 网络安全
JDBC数据库编程(java实训报告)
这篇文章是关于JDBC数据库编程的实训报告,涵盖了实验要求、实验环境、实验内容和总结。文中详细介绍了如何使用Java JDBC技术连接数据库,并进行增删改查等基本操作。实验内容包括建立数据库连接、查询、添加、删除和修改数据,每个部分都提供了相应的Java代码示例和操作测试结果截图。作者在总结中分享了在实验过程中遇到的问题和解决方案,以及对Java与数据库连接操作的掌握情况。
JDBC数据库编程(java实训报告)
|
1天前
|
Java 关系型数据库 MySQL
"解锁Java Web传奇之旅:从JDK1.8到Tomcat,再到MariaDB,一场跨越数据库的冒险安装盛宴,挑战你的技术极限!"
【8月更文挑战第19天】在Linux上搭建Java Web应用环境,需安装JDK 1.8、Tomcat及MariaDB。本指南详述了使用apt-get安装OpenJDK 1.8的方法,并验证其版本。接着下载与解压Tomcat至`/usr/local/`目录,并启动服务。最后,通过apt-get安装MariaDB,设置基本安全配置。完成这些步骤后,即可验证各组件的状态,为部署Java Web应用打下基础。
6 1
|
6天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。
|
5天前
|
SQL 存储 Java
完整java开发中JDBC连接数据库代码和步骤
该博客文章详细介绍了使用JDBC连接数据库的完整步骤,包括加载JDBC驱动、提供连接URL、创建数据库连接、执行SQL语句、处理结果以及关闭JDBC对象的过程,并提供了相应的示例代码。
|
5天前
|
算法 关系型数据库 MySQL
一天五道Java面试题----第七天(mysql索引结构,各自的优劣--------->事务的基本特性和隔离级别)
这篇文章是关于MySQL的面试题总结,包括索引结构的优劣、索引设计原则、MySQL锁的类型、执行计划的解读以及事务的基本特性和隔离级别。
|
5天前
|
存储 设计模式 安全
Java GenericObjectPool 对象池化技术--SpringBoot sftp 连接池工具类
Java GenericObjectPool 对象池化技术--SpringBoot sftp 连接池工具类
5 0
|
存储 消息中间件 缓存
面试疑难点解析——Java数据库开发(一)
阿里云再offer 5000人,数据库人才求贤若渴!7月9日 19:00,阿里云数据库事业部的两位技术大咖在线直招10多个岗位,想要进入阿里云吗?快来投递简历吧:https://developer.aliyun.com/special/offerday01
面试疑难点解析——Java数据库开发(一)