天天看点

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

文章目录

  • 1.原理深度解析
    • 1.1注册驱动
    • 1.2获取连接
    • 1.3 获取数据库操作对象
    • 1.4执行sql语句
    • 1.5处理查询结果
    • 1.6释放资源
  • 2.账户转账
  • 3.JDBC工具类包装
    • 3.1包装工具类
    • 3.2使用工具类实现模糊查询

【Mysql】JDBC从放弃到入门(上)

【Mysql】JDBC从放弃到入门(中)

【Mysql】JDBC从放弃到入门(下)

1.原理深度解析

1.1注册驱动

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

从驱动程序的源码中也可以看出com.mysql.cj.jdbc.Driver实现了java.sql.Driver这个接口。

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

registerDriver方法:

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

1.2获取连接

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

url:

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

getConnection方法:

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

1.3 获取数据库操作对象

Statement stmt = conn.createStatement();
【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

1.4执行sql语句

int count = stmt.executeUpdate(sql);
【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

1.5处理查询结果

1.6释放资源

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

2.账户转账

我们在数据库中并发操作的时候可能导致丢失修改,比如下面的例子。

sql脚本

drop table if exists t_act;
CREATE TABLE t_act(
	actno int,
	balance double(7,  2)
);
insert into t_act(actno, balance) values(111,20000);
insert into t_act(actno,balance) values(222,0);
commit;
select * from t_act;
           
package com.sdnu;

import java.sql.*;

/**
 * @author Beyong
 * @Description bank
 * @date 2021/07/21 16:07
 */
public class bank {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try{
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mydatabase?" +
                    "useUnicode=true&characterEncoding=utf-8&zeroDate" +
                    "TimeBehavior=convertToNull&allowMultiQueries=true&ser" +
                    "verTimezone=Asia/Shanghai&useSSL=false";
            String user = "root";
            String passWord = "123";
            conn = DriverManager.getConnection(url,user,passWord);
            String sql = "UPDATE t_act SET balance=? WHERE actno=?";
            ps = conn.prepareStatement(sql);
            ps.setDouble(1,10000);
            ps.setInt(2,111);
            int count = ps.executeUpdate();

            String s = null;
            s.toString();

            ps = conn.prepareStatement(sql);
            ps.setDouble(1,10000);
            ps.setInt(2,222);
            count += ps.executeUpdate();
        }catch(SQLException e){
            e.printStackTrace();
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }finally{
            if(conn != null){
                try{
                    conn.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
            if(ps != null){
                try{
                    ps.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
        }
    }
}
           

我们专门设置一个异常在两个事务之间:

String s = null;

s.toString();

【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

我们发现少了1000元。

于是我们修改我们的代码为如下:

package com.sdnu;

import java.sql.*;

/**
 * @author Beyong
 * @Description bank
 * @date 2021/07/21 16:07
 */
public class bank {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        try{
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/mydatabase?" +
                    "useUnicode=true&characterEncoding=utf-8&zeroDate" +
                    "TimeBehavior=convertToNull&allowMultiQueries=true&ser" +
                    "verTimezone=Asia/Shanghai&useSSL=false";
            String user = "root";
            String passWord = "123";
            conn = DriverManager.getConnection(url,user,passWord);
            //将自动提交事务改为手动
            conn.setAutoCommit(false);//开启事务

            String sql = "UPDATE t_act SET balance=? WHERE actno=?";
            ps = conn.prepareStatement(sql);
            ps.setDouble(1,10000);
            ps.setInt(2,111);
            int count = ps.executeUpdate();

            String s = null;
            s.toString();

            ps = conn.prepareStatement(sql);
            ps.setDouble(1,10000);
            ps.setInt(2,222);
            count += ps.executeUpdate();

            System.out.println(count == 2 ? "转账成功" : "转账失败");
            //程序走到这个说明程序没有错误,可以提交,手动提交,事务结束。
            conn.commit();
        }catch(Exception e){
            if(conn != null){
                try{
                    conn.rollback();//回滚
                }catch(SQLException e1){
                    e1.printStackTrace();
                }
            }
        } finally{
            if(ps != null){
                try{
                    ps.close();
                }catch(SQLException e){
                    e.printStackTrace();
                }
            }
        }
    }
}
           

三行重要代码:

(1)conn.setAutoCommit(false);//开启事务

(2) conn.commit();//提交事务

(3) conn.rollback();//回滚

3.JDBC工具类包装

3.1包装工具类

为了以后使用方便我们可以将JDBC包装成工具类。以后直接调用即可。

package com.sdnu.utils;

import java.sql.*;

/**
 * @author Beyong
 * @Description JDBC工具类
 * @date 2021/07/21 18:26
 */
public class DBUtil {
    /**
     *工具类中的方法都是私有的
     * 工具类中的方法都是静态的
     */
    private DBUtil(){};
    static{
        try{
            Class.forName("com.mysql.cj.jdbc.Driver");
        }catch(ClassNotFoundException e){
            e.printStackTrace();
        }
    }
    /**
     * @author: Beyong
     * @description:获取连接对象
     * @param: []
     * @return: java.sql.Connection
     * @date: 2021/7/21 18:38
     */
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase?" +
                    "useUnicode=true&characterEncoding=utf-8&zeroDate" +
                    "TimeBehavior=convertToNull&allowMultiQueries=true&ser" +
                    "verTimezone=Asia/Shanghai&useSSL=false","root","123");
    }
    /**
     * @author: Beyong
     * @description: 关闭资源
     * @param: [java.sql.Connection, java.sql.Statement, java.sql.ResultSet]
     * @return: void
     * @date: 2021/7/21 18:45
     */
    public static void close(Connection conn, Statement ps, ResultSet rs){
        if( conn != null){
            try{
                 rs.close();
            }catch(SQLException e){
                e.printStackTrace();
            }
        }
        if(ps != null){
            try{
                ps.close();
            }catch(SQLException e){
                e.printStackTrace();
            }
        }
        if( rs != null){
            try{
                rs.close();
            }catch(SQLException e){
                e.printStackTrace();
            }
        }
    }
}

           

3.2使用工具类实现模糊查询

package com.sdnu;

import com.sdnu.utils.DBUtil;

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

/**
 * @author Beyong
 * @Description 测试JDBC工具
 * @date 2021/07/21 18:54
 */
public class DBUtilTest {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try{
            //获取连接
            conn = DBUtil.getConnection();
            String sql = "SELECT loginName FROM t_user WHERE realName like ?";
            ps = conn.prepareStatement(sql);
            ps.setString(1,"x%");
            rs = ps.executeQuery();
            while(rs.next()){
                System.out.println(rs.getString("loginName"));
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            DBUtil.close(conn, ps, rs);
        }
    }
}

           
【Mysql】JDBC从放弃到入门(下)1.原理深度解析2.账户转账3.JDBC工具类包装

作者:Beyong    

出处:Beyong博客

github地址:https://github.com/beyong2019

本博客中未标明转载的文章归作者Beyong有,欢迎转载,但未经作者同意必须保留此段声明,且在文章明显位置给出原文连接,否则保留追究法律责任的权利。