【JavaSE高级】JDBC编程

JDBC

Java数据库连接(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。

值得注意的是:JDBC仅仅是一个规范而不是一个实现。意思是各种不同类型的数据库都依这种规范有相应的实现,它们之间的具体实现都是由java类和接口组成。本文中的代码都是针对MySQL数据库实现的。

在这里插入图片描述

JDBC常用对象
API说明通俗理解
java.sql.Connection与特定数据库的连接。能通过getMetaData方法获得数据库提供的信息,所支持的SQL语法、存储过程和此连接的功能等信息。代表了数据库。获得了Connection对象,就相当于连接通了数据库
java.sql.Driver每个驱动程序类必需实现的接口,同时,每个数据库驱动程序都应该提供一个实现Driver接口的类。
java.sql.DriverManager(Class)管理一组JDBC驱动程序的基本服务。作为初始化的一部分,此接口会尝试加载在"jdbc.drivers"系统属性中引用的驱动程序.只是一个辅助类,是工具。是为了获取Connection对象的辅助类
java.sql.Statement用于执行静态SQL语句并返回其生成结果的对象执行静态sql语句
java.sql.PreparedStatement继承Statement接口,表示预编译的SQL语句的对象,SQL语句被预编译并且存储在PreparedStatement对象中。然后可以使用此对象高效地多次执行该语句。更加高效的执行sql语句
java.sql.CallableStatement用来访问数据库中的存储过程。它提供了一些方法来指定语句所使用的输入、输出参数。
java.sql.ResultSet指的是查询返回的数据库结果集。封装查询语句返回的结果
java.sql.ResultSetMetaData可用于获取关于ResultSet对象中列的类型和属性信息的对象。

表格参考:https://blog.csdn.net/weixin_43691058/article/details/103907259

JDBC编程步骤

在此处我使用的是maven所快速搭建的项目。

1、导入依赖

当 A jar 包用到了 B jar 包中的某些类时,A 就对 B 产生了依赖。在项目中以依赖的方式引入一个我们需要的 jar 包,只需要使用 dependency 标签指定被依赖 jar 包的坐标就可以了。如果我们将maven的镜像配置文件更改为了阿里云,那么我们就可以直接去阿里仓库寻找我们所需要的依赖。

在这里插入图片描述

2、参数配置
//参数配置
private String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
private String useName; //用户名
private String passWord; //密码
private String jdbcDriver = "com.mysql.jdbc.Driver"; //jdbc驱动
private Connection connection; //JDBC与MySQL所建立的连接
  • url:确定我们所需要连接的数据库。
    • jdbc:mysql:和mysql建立连接时使用的协议。
    • 127.0.0.1:mysql服务器所在的ip地址。(此处为本机)
    • 3306:mysql服务器所在的端口号。(此处为MySQL的默认端口)
    • test:即需要操作的数据库名。
  • useName:即登录数据库时所需要的用户名。
  • passWord:即登录数据库时所需要的密码。
  • jdbcDriver:使用jdbc时所需要的驱动。
3、加载驱动
Class.forName(jdbcDriver); //加载驱动
4、建立连接
connection = DriverManager.getConnection(url,useName,passWord); //建立连接

加载驱动与建立连接的完整代码:

//加载驱动(驱动加载完成后就可以使用JDBC了)
//建立连接
public void createConnection(){
    try {
        Class.forName(jdbcDriver); //加载驱动
        try {
            connection = DriverManager.getConnection(url,useName,passWord); //建立连接
            //getConnection方法就是JDBC提供给我们建立连接的方法
            //即登录到MySQL服务器的过程
            if(!connection.isClosed()){
                //判断是否成功建立连接
                System.out.println("连接建立成功");
            }else {
                System.out.println("连接建立失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}
5、操作数据库

在这里,JDBC提供了两种操作数据库的对象:Statement 和 PreparedStatement。它们两个的介绍可以看上面的表格。

我们需要注意的是:

当同结构的SQL语句执行多次时,使用PrePareStatement创建对象的执行效率要比使用Statement创建对象的效率高得多。原因是用PrePareStatement创建对象只编译一次,下一次传值只从解析树之后的操作进行,而使用Statement创建对象每次都需要从头编译。

但并不是使用PrePareStatement创建对象的执行效率总比使用Statement创建对象的效率高,当一个结构的SQL语句只执行一次时,用Statement创建对象的执行效率要比使用PrePareStatement创建对象的效率高,原因是用Statement创建对象会直接执行完一条SQL语句,而用PrePareStatement创建对象会在判断SQL语句没有问题后停止线程等待参数传递,此时会使效率低下。

因此在不同的使用场景下要使用不同的对象。其实在实际操作过程中,更多的是使用PrePareStatement创建对象,原因是使用Statement创建对象容易产生SQL注入异常。

在这里插入图片描述

而对于正常的操作数据库而言,两者的操作基本是相同的:

  • 对数据造成改变的,如insert、update、delete,我们使用的是executeUpdate();方法。
  • 对数据不造成改变的,如select,我们使用的是executeQuery();方法。
  • 当我们进行select查询语句时,jdbc会给我们返回ResultSet类型的集合,即查询到的结果集的集合。此时,我们需要通过遍历集合的方法达到查询的操作,例如:while (resultSet.next()); //resultSet.next()判断集合中是否还有数据。

以插入数据为例,我们来看看Statement 和 PreparedStatement两种对象在具体操作上有什么不同。

  • Statement对象
//操作数据库(增删改查操作)
public void insertTest(){ //update delete
    String insertSql = "insert into jdbc_test values(1,'jdbc_test')";
    try {
        statement.executeUpdate(insertSql);
        //executeUpdate方法是所有会对数据库数据进行修改的统一方法
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

我们可以看到,statement对象需要将SQL语句完整的写出来,再进行SQL语句的执行。

  • PreparedStatement对象
//操作数据库(增删改查操作)
public void insertTest(){ //update delete
    String insertSql = "insert into jdbc_test values(?,?)"; //定义无参的SQL语句
    PreparedStatement pre = null;
    try {
        pre = connection.prepareStatement(insertSql); //将无参的SQL语句提交给MySQL
        //根据字段的不同数据类型给无参的SQL语句提交参数
        pre.setInt(1,2);
        pre.setString(2,"jdbc_pre");
        pre.executeUpdate(); //执行SQL语句
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        try {
            pre.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

我们可以看到,PreparedStatement对象会先对无参的SQL语句进行解析,完成后再进行传值,此时就会避免SQL注入异常,大大的提高了数据库的安全性。

6、关闭数据库连接
connection.close(); //当不再使用数据库时,关闭JDBC连接避免资源浪费
//关闭数据库连接
public void closeConnection(){
    try {
        connection.close(); //当不再使用数据库时,关闭JDBC连接避免资源浪费
        if(connection.isClosed()){
            System.out.println("连接已关闭");
        }else {
            System.out.println("连接关闭失败");
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
JDBC操作事务

我们都知道MySQL的事务也是数据库中常用的操作,关于MySQL的事务可以查看MySQL事务

在这里,我们来用Java代码来测试一下事务的实现。

1、进行MySQL数据库的连接

见上面的JDBC编程步骤。

2、开启事务
connection.setAutoCommit(false); //开启事务(相当于 SET AUTOCOMMIT = 0;)
3、设置事务的隔离级别
//开启事务的隔离级别(相当于 set session transaction isolation level READ COMMITTED;)
//此处更改隔离级别为序列化级别
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);

具体代码:

//加载驱动(驱动加载完成后就可以使用JDBC了)
//建立连接
public void createConnection(){
    try {
        Class.forName(jdbcDriver); //加载驱动
        try {
            connection = DriverManager.getConnection(url,useName,passWord); //建立连接
            //getConnection方法就是JDBC提供给我们建立连接的方法
            //即登录到MySQL服务器的过程
            if(!connection.isClosed()){
                //判断是否成功建立连接
                System.out.println("连接建立成功");
                connection.setAutoCommit(false); //开启事务(相当于 SET AUTOCOMMIT = 0;)
                //开启事务的隔离级别(相当于 set session transaction isolation level READ COMMITTED;)
                //此处更改隔离级别为序列化级别
                connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
            }else {
                System.out.println("连接建立失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}
4、回滚操作测试
//事务的回滚方法测试
public void rollbackTest(){
    String selectSql = "select * from jdbc_test";
    String insertSql = "insert into jdbc_test values(?,?)";
    PreparedStatement selectPre = null,insertPre = null;
    try {
        selectPre = connection.prepareStatement(selectSql);
        insertPre = connection.prepareStatement(insertSql);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    selectTest(selectPre);
    insertTest(insertPre,3,"jdbc_test");
    insertTest(insertPre,4,"jdbc_test");
    selectTest(selectPre);
    try {
        connection.rollback();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    selectTest(selectPre);
}
public static void main(String[] args) {
        JDBC_Tran jdbc = new JDBC_Tran();
        jdbc.createConnection();
        jdbc.rollbackTest();
        jdbc.closeConnection();
    }

测试结果:
在这里插入图片描述

5、提交操作测试
//事务的提交操作测试
public void commitTest(){
    String selectSql = "select * from jdbc_test";
    String insertSql = "insert into jdbc_test values(?,?)";
    PreparedStatement selectPre = null,insertPre = null;
    try {
        selectPre = connection.prepareStatement(selectSql);
        insertPre = connection.prepareStatement(insertSql);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    selectTest(selectPre);
    insertTest(insertPre,3,"jdbc_test");
    insertTest(insertPre,4,"jdbc_test");
    selectTest(selectPre);
    try {
        connection.commit();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    try {
        connection.rollback();
    } catch (SQLException e) {
        e.printStackTrace();
    }
    selectTest(selectPre);
}
public static void main(String[] args) {
        JDBC_Tran jdbc = new JDBC_Tran();
        jdbc.createConnection();
        jdbc.commitTest();
        jdbc.closeConnection();
    }

测试结果:

在这里插入图片描述

6、保存点回滚操作
//设置保存点、退回保存点测试
public void pointTest(){
    String selectSql = "select * from jdbc_test";
    String insertSql = "insert into jdbc_test values(?,?)";
    PreparedStatement selectPre = null,insertPre = null;
    try {
        selectPre = connection.prepareStatement(selectSql);
        insertPre = connection.prepareStatement(insertSql);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    selectTest(selectPre);
    insertTest(insertPre,3,"jdbc_test");
    insertTest(insertPre,4,"jdbc_test");
    try {
        Savepoint point1 = connection.setSavepoint("p1");
        insertTest(insertPre,5,"jdbc_test");
        insertTest(insertPre,6,"jdbc_test");
        selectTest(selectPre);
        connection.rollback(point1);
        selectTest(selectPre);
    } catch (SQLException e) {
        e.printStackTrace();
    }
    try {
        connection.rollback();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
public static void main(String[] args) {
        JDBC_Tran jdbc = new JDBC_Tran();
        jdbc.createConnection();
        jdbc.pointTest();
        jdbc.closeConnection();
    }

测试结果:

在这里插入图片描述

7、关闭连接

见上面的JDBC编程步骤。

JDBC实现:

public class JDBC {
    //导入jdbc的MySQL依赖 -> pom.xml
    //参数配置
    private String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
    private String useName;
    private String passWord;
    private String jdbcDriver = "com.mysql.jdbc.Driver"; //jdbc驱动
    private Connection connection; JDBC与MySQL所建立的连接
    //加载驱动(驱动加载完成后就可以使用JDBC了)
    //建立连接
    public void createConnection(){
        try {
            Class.forName(jdbcDriver); //加载驱动
            try {
                connection = DriverManager.getConnection(url,useName,passWord); //建立连接
                //getConnection方法就是JDBC提供给我们建立连接的方法
                //即登录到MySQL服务器的过程
                if(!connection.isClosed()){
                    //判断是否成功建立连接
                    System.out.println("连接建立成功");
                }else {
                    System.out.println("连接建立失败");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    //开启或者关闭事务
    public void setAutoCommit(){
        try {
            if(!connection.isClosed()){
                if(connection.getAutoCommit()){
                    connection.setAutoCommit(false); //开启事务
                    System.out.println("当前事务已开启");
                }else {
                    connection.setAutoCommit(true); //关闭事务
                    System.out.println("当前事务已关闭");
                }
            }else {
                System.out.println("当前数据库未连接");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //更改事务的隔离级别
    public void setTransactionIsolation(int level){
        try {
            if(!connection.getAutoCommit()){
                connection.setTransactionIsolation(level);
            }else {
                System.out.println("当前事务未开启");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //操作数据库(增删改查操作)
    //插入数据
    public void insertTest(int id,String name){ //update delete
        String insertSql = "insert into jdbc_test values(?,?)"; //定义无参的SQL语句
        PreparedStatement pre = null;
        try {
            pre = connection.prepareStatement(insertSql); //将无参的SQL语句提交给MySQL
            //根据字段的不同数据类型给无参的SQL语句提交参数
            pre.setInt(1,id);
            pre.setString(2,name);
            pre.executeUpdate(); //执行SQL语句
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                pre.close();
                dataToDetermine();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //删除数据
    public void deleteTest(int id){
        String deleteSql = "delete from jdbc_test where id = ?";
        PreparedStatement pre = null;
        try {
            pre = connection.prepareStatement(deleteSql);
            pre.setInt(1,id);
            pre.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                pre.close();
                dataToDetermine();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //更改数据
    public void updateTest(int id,String name){
        String updateSql = "update jdbc_test set name = ? where id = ?";
        PreparedStatement pre = null;
        try {
            pre = connection.prepareStatement(updateSql);
            pre.setString(1,name);
            pre.setInt(2,id);
            pre.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                pre.close();
                dataToDetermine();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //查询数据
    public void selectTest(){
        String selectSql = "select * from jdbc_test";
        PreparedStatement pre = null;
        try {
            pre = connection.prepareStatement(selectSql);
            ResultSet resultSet = pre.executeQuery(); //resultSet查询到的结果集的集合
            //executeQuery方法是执行查询操作的专用方法
            //通过遍历集合的方法达到查询的操作
            while (resultSet.next()){ //resultSet.next()判断集合中是否还有数据
                System.out.println("id:"+resultSet.getString(1)
                        +" name:"+resultSet.getString(2));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                pre.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        System.out.println();
    }
    //当开启事务时进行提交操作
    public void dataToDetermine(){
        try {
            if(connection.getAutoCommit()){
                return;
            }else {
                System.out.print("是否正式提交SQL语句(yes/no):");
                Scanner scanner = new Scanner(System.in);
                String input = scanner.next();
                if(input.equals("yes") || input.equals("y")){
                    connection.commit();
                }else {
                    connection.rollback();
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //关闭数据库连接
    public void closeConnection(){
        try {
            connection.close(); //当不再使用数据库时,关闭JDBC连接避免资源浪费
            if(connection.isClosed()){
                System.out.println("连接已关闭");
            }else {
                System.out.println("连接关闭失败");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值