【JDBC】-- 考虑事务的增删改操作

1、什么是数据库事务

一组逻辑操作单元,使数据从一种状态变换到另一种状态。(一组逻辑操作单元:一个或多个DML操作)

案例:用户AA向用户BB转账100。

sql语句:

update user_table set balance = balance - 100 where user = ?;

update user_table set balance = balance + 100 where user = ?;

如果在第一条语句后出现异常导致第二条语句没有执行,那么数据库已经执行了第一条语句,则会出现账户只减不加的情况,所以需要两条语句都执行后,一起在数据库执行,要么都执行,要么都不执行,这时需要使用事务来解决。

2、事务处理的原则

保证所有事务都作为一个工作单元来执行,即使出现故障,都不能改变这种执行方式。

当在一个事务中执行多个操作时,要么所有事务都被提交,那么这些修改就永久保存;

要么数据库管理系统将放弃所作的所有修改,整个事务回滚到最初状态。

3、数据一旦提交,就不可回滚

4、哪些操作会导致数据的自动提交

①DDL操作一旦执行,都会自动提交(setAutoCommit失效);

②DML默认情况,自动提交,但可以通过setAutoCommit取消自动提交;

③默认再关闭连接时,会自动提交数据。

一、代码实现

前提

创建jdbc.properties配置文件

封装连接数据库的基本信息

user=root
password=ad
url=jdbc:mysql://localhost:3306/jdbc?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT
driverClass=com.mysql.cj.jdbc.Driver

创建软件包unil,软件包下创建JDBCUtils类

封装连接数据库、关闭的方法

package util;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
/**封装数据库连接和关闭*/
public class JDBCUtils {
    public static Connection getConnection() throws Exception{
        //读取配置文件基本信息
        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
        Properties pros = new Properties();
        pros.load(is);

        String user = pros.getProperty("user");
        String password = pros.getProperty("password");
        String url = pros.getProperty("url");
        String driverClass = pros.getProperty("driverClass");
        //加载驱动
        Class.forName(driverClass);
        //获取连接
        Connection conn = DriverManager.getConnection(url,user,password);
        return conn;
    }
    public static void closeResource(Connection conn, Statement ps){
        try {
            if(ps != null)
                ps.close();
        }catch (SQLException e){
            e.printStackTrace();
        }
        try {
            if(conn != null)
                conn.close();
        }catch (SQLException e){
            e.printStackTrace();
        }
    }
    public static void closeResource(Connection conn, Statement ps, ResultSet rs){
        try {
            if(ps != null)
                ps.close();
        }catch (SQLException e){
            e.printStackTrace();
        }
        try {
            if(conn != null)
                conn.close();
        }catch (SQLException e){
            e.printStackTrace();
        }
        try {
            if(rs!=null)
                rs.close();
        }catch (SQLException e){
            e.printStackTrace();
        }
    }
}

 考虑事务的增删改操作

与前面不同的是,需要传入连接的数据库。

在调用通用的增删改方式时,连接数据库,取消自动提交,在sql语句都执行完成时,再提交数据,出现异常则回滚事务,最后需要恢复自动提交。

setAutoCommit()设置自动提交状态

commit()提交数据

rollback()回滚数据

 public static void testUpdateWithTx(){
        Connection conn = null;
        try {
            conn = JDBCUtils.getConnection();
            //取消自动提交
            conn.setAutoCommit(false);

            String sql = "update user_table set balance = balance - 100 where user = ?";
            update(conn,sql,"AA");

            //模拟网络异常
            System.out.println(10/0);

            String sql1 = "update user_table set balance = balance + 100 where user = ?";
            update(conn,sql1,"BB");

            System.out.println("转账成功");

            //提交数据
            conn.commit();
        }catch (Exception e){
            e.printStackTrace();
            //回滚数据
            try {
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        }finally {
            //恢复自动提交
            try {
                conn.setAutoCommit(true);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            JDBCUtils.closeResource(conn,null);
        }

    }
   
 /**通用增删改操作(考虑事务)*/
    public static void update(Connection conn,String sql,Object ...args){//args可变形参,占位符长度
        PreparedStatement ps = null;
        try {
            //预编译
            ps = conn.prepareStatement(sql);
            //填充占位符
            for(int i = 0;i

你可能感兴趣的:(JDBC,数据库,java,sql,jdbc)