03-JDBC的事务机制

JDBC的事务机制

1、事务演示

package ajdbctest;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/*
    JDBC事务机制:
        JDBC中的事务是自动提交的,只要执行任意一条DML语句,就会自动提交一次。
        这是JDBC默认的事务行为。
        然而在实际的业务中,需要N条DML语句共同联合才能完成,必须保证它们这些DML语句
        同时成功或者同时失败

        下面演示关闭事务自动提交机制的转账演示事务
        drop table if exists t_acn;
        create table t_acn(
            account int,
            balance double(7,2)
        )
        select * from t_acn;
        上面的7表示7为有效数字,2表示保留的小数点数

        通过演示,可以发现,在执行了一条DML语句后
        当我们把一个异常放进去影响了后面的DML语句时,数据库中的数据并没有发生改变,实现了回滚
        然后把异常去掉,程序正常执行,数据库表中数据正常改变

        重点三行代码:
        conn.setAutoCommit();
        conn.commit();
        coon.rollback();
 */
public class JDBCTest09 {

    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement ps = null;

        try {
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");

            //获取连接(在获取连接后,用Connection接口中的setAutoCommit方法关闭自动提交
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mysqlstudy?useSSL=false","root","rong195302");
            conn.setAutoCommit(false);//true表示开启自动提交,false表示关闭。这里开始事务

            //获取预编译数据库操作对象
            String sql1 = "update t_acn set balance = ? where account = ?";
            ps = conn.prepareStatement(sql1);
            //给?传值
            ps.setDouble(1,10000.00);
            ps.setInt(2,111);

            //执行sql
            int count = ps.executeUpdate();

//            //在这里设置一个一定会出现异常的语句,使下面的语句包括第二条DML语句无法成功执行
//            //来模拟多条DML语句完成一个事务当一条DML语句没有成功时的情形
//            //这里会出现空指针异常,下面的提交事务没法执行,在try这个空指针异常的catch语句块中编写回滚事务的代码
//            //使事务开始后做的操作回到事务开始前
//            String i = null;
//            i.toString();

            //
            String sql2 = "update t_acn set balance = ? where account = ?";
            ps = conn.prepareStatement(sql2);
            //给?传值
            ps.setDouble(1,10000.00);
            ps.setInt(2,222);

            //执行sql
            count += ps.executeUpdate();

            System.out.println(count==2?"转账成功":"转账失败");

            //程序能执行到这里说明以上程序没有异常,事务结束,手动提交数据
            conn.commit();

        } catch (NullPointerException e){
            //这里回滚(这里是为了演示事务失败结束而随便让其出的异常)
            if (conn == null) {
                try {
                    conn.rollback();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
          e.printStackTrace();
        }catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }

    }

}

2、编写JDBC工具类和实现模糊查询

package ajdbctest.utils;

import java.sql.*;

/**
    JDBC工具类,将JDBC编程的一些步骤封装进一个工具类中,简化每一次的JDBC操作
 */
public class DBUtil {

    /**
     * 不能每次调用获取连接对象的方法都注册驱动,所以将注册驱动的语句放到工具类中的静态语句块中
     * 在第一次类名.工具中的方法时,加载工具类,只加载一次,所以静态语句块在加载该类时执行,只执行一次
     */
    static{
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    /**
     * 工具类中的构造方法都是私有的
     * 因为工具类中的方法都是静态的,直接类名.调用,不需要new对象
     * 为了防止别人new工具类的对象直接将其构造方法私有化
     */
    private DBUtil(){}

    /**
     * 一个获取连接的方法
     * @return  返回一个连接到某个数据库的Connection对象
     * @throws SQLException 这里上抛异常,不做try catch处理,该方法是放进try语句块中执行的
     */
    public static Connection getConnection() throws SQLException {

        return DriverManager.getConnection("jdbc:mysql://localhost:3306/mysqlstudy?useSSL=false","root","rong195302");

    }

    /**
     * 关闭资源的方法,这里不需要抛出异常,因为不是在try catch中执行的
     * @param conn  数据库连接对象
     * @param ps    数据库操作对象或者是数据库预编译操作对象
     * @param rs    结果集对象
     */
    public static void close(Connection conn, Statement ps, ResultSet rs){

        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (ps != null) {
            try {
                ps.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if (conn!= null) {
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

}

package ajdbctest;

import ajdbctest.utils.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 *  1、在本类中测试DBUtil工具类的使用
 *  2、如何实现模糊查询
 */
public class JDBCTest10 {

    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            //注册驱动和获取数据库连接对象
            conn = DBUtil.getConnection();

            //获取预编译数据库操作对象
            //查询第二各字母为A的名字
            /*错误写法
            String sql = "select ename from emp where ename like '_?%'";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"A");
            */
            String sql = "select ename from emp where ename like ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"_A%");

            //执行sql语句
            rs = ps.executeQuery();

            //处理查询结果集
            while(rs.next()){
                System.out.println(rs.getString("ename"));
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DBUtil.close(conn,ps,rs);
        }

    }

}

上一篇:mybatis入门笔记


下一篇:jdbc访问数据库-修改