【Java】学JDBC看这篇文章就够了—JDBC保姆级教程

目录

一、JDBC概述

基本介绍

JDBC相关API

二、连接mysql数据库

准备工作

JDBC程序编写步骤

五种连接数据库的方式 

三、ResultSet(结果集)

基本介绍

四、Statement 和 PreparedStatement

Statement

PreparedStatement 

五、事务

基本介绍

六、批处理

基本介绍

七、数据库连接池

传统获取Connection问题分析

数据库连接池种类

Druid数据库连接池

八、Apache-DBUtils类库

基本介绍

使用DBUtils类库进行查询操作

使用DBUtils类库进行增删改操作

九、最后的话


一、JDBC概述

基本介绍

        1. JDBC为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。

        2. Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。 

        3. JDBC基本原理示意图

【Java】学JDBC看这篇文章就够了—JDBC保姆级教程_第1张图片

        4. JDBC是Java提供一套用于数据库操作的接口API,Java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。

【Java】学JDBC看这篇文章就够了—JDBC保姆级教程_第2张图片

JDBC相关API

【Java】学JDBC看这篇文章就够了—JDBC保姆级教程_第3张图片


二、连接mysql数据库

准备工作

        1. 创建一个 lib 目录

        2. 将 mysql-connector-java .jar  驱动复制进去(点击蓝色字体即可下载)

        3. 右键添加到 Library

【Java】学JDBC看这篇文章就够了—JDBC保姆级教程_第4张图片

JDBC程序编写步骤

        1. 注册驱动 - 加载 Driver 类

        2. 获取连接 - 得到 Connection

        3. 执行增删改查 - 发送 SQL 给mysql执行

        4. 释放资源 - 关闭相关连接

五种连接数据库的方式 

        方式一:

package JDBC.Linkedways;

import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class linkedways1 {
    public static void main(String[] args) throws SQLException {
        //前提准备:导入mysql驱动

        //1.注册驱动
        Driver driver = new Driver();

        //2. 获取mysql连接
        // mysql连接地址  jdbc:mysql://IP:端口/数据库
        //此处我连接的时本地数据库,可以指定 ip 地址连接
        String url = "jdbc:mysql://localhost:3306/test";
        // Properties 文件存储用户名和密码
        Properties properties = new Properties();
        // user - 用户名   password — 密码  按此要求存入用户名和密码
        properties.setProperty("user", "root");
        properties.setProperty("password", "123456");
        // 按照指定的 url 和 Properties 获取连接
        Connection connect = driver.connect(url, properties);

        //3.执行增删改查
        //mysql语句
        String sql = "insert into jdbc values (1,'Mike',19)";

        Statement statement = connect.createStatement();
        //返回该指令影响的行数,为0则代表未执行成功
        int i = statement.executeUpdate(sql);
        System.out.println(i > 0 ? "yes" : "no");
        
        // 4. 释放资源
        connect.close();
        statement.close();

    }
}

        方式二:

package JDBC.Linkedways;

import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class linkedways2 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
        //1. 加载 Driver 类 ,此处用类加载
        Class aClass = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) aClass.newInstance();

        //2. 获取mysql连接
        String url = "jdbc:mysql://localhost:3306/test";
        Properties properties = new Properties();
        properties.setProperty("user", "root");
        properties.setProperty("password", "123456");
        Connection connect = driver.connect(url, properties);

        //3. 执行mysql语句
        Statement statement = connect.createStatement();
        String sql = "update jdbc set age=age+1 where id = 1";
        int i = statement.executeUpdate(sql);
        System.out.println(i);

        //4. 关闭资源
        connect.close();
        statement.close();
    }
}

        方式三:

package JDBC.Linkedways;

import com.mysql.jdbc.Driver;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;


public class linkedways3 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, SQLException {
        //1. 加载 Driver 类
        Class aClass = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) aClass.newInstance();

        //2. 连接mysql数据库
        String url = "jdbc:mysql://localhost:3306/test";
        //利用 Properties 文件获取用户名和密码
//        Properties properties = new Properties();
//        properties.setProperty("user", "root");
//        properties.setProperty("password", "123456");
//        Connection connection = DriverManager.getConnection(url, properties);

        //直接利用变量获取用户名和密码
        String user = "root";
        String password = "123456";
        DriverManager.registerDriver(driver);//可省略
//        com.mysql.jdbc.Driver //追进 Driver 类 可以发现在类加载的时候会自动注册
        /*
                static {
                        try {
                            DriverManager.registerDriver(new Driver());
                        } catch (SQLException var1) {
                            throw new RuntimeException("Can't register driver!");
                        }
                    }
         */
        //利用 DriverManager 类的 getConnection() 方法
        Connection connection = DriverManager.getConnection(url, user, password);

        //3. 执行mysql命令
        String sql = "insert into jdbc values (2,'Milan',20)";

        Statement statement = connection.createStatement();

        statement.executeUpdate(sql);

        //4. 关闭资源
        statement.close();
        connection.close();

    }
}

        方式四:

package JDBC.Linkedways;

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

public class linkedways4 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 1. 加载 Driver 类
        Class.forName("com.mysql.jdbc.Driver");
//        com.mysql.jdbc.Driver //追进Driver类 可以发现在类加载的时候会自动注册
        /*
                static {
                    try {
                        DriverManager.registerDriver(new Driver());
                    } catch (SQLException var1) {
                        throw new RuntimeException("Can't register driver!");
                    }
                }
         */
        // 2. 连接mysql
        String url = "jdbc:mysql://localhost:3306/test";
        String user = "root";
        String password = "123456";
        Connection connection = DriverManager.getConnection(url, user, password);

        // 3. 执行mysql语句
        String sql = "delete from jdbc where id = 4";
        Statement statement = connection.createStatement();
        statement.executeUpdate(sql);

        // 4. 关闭资源
        statement.close();
        connection.close();

    }
}

        方式五:

package JDBC.Linkedways;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class linkedways5 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
        //在4的基础上进行改进,通过读取外部配置文件来读取需要的数据,而不是直接在代码里写
        //这样我们可以在配置文件修改信息而程序不需要重新编译
        //准备工作
        //将外部配置文件读取进内存 FileInputStream
        Properties properties = new Properties();
        properties.load(new FileInputStream(new File("src/mysql.properties")));
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        //1. 加载Driver
        Class.forName(driver);//可不写
        /**
         * 1. mysql驱动 5.1.6 可以无需Class.forName(driver);
         * 2. 从JDK1.5以后使用的jdbc4,不再需要显示调用 Class.forName(driver) 注册驱动
         *    而是自动调用驱动jar包下的META-INF\java.sql.Driver 文本中的类名称去注册
         * 3. 建议还是写上,这样会更加明确。
         */

        //2. 连接mysql
        Connection connection = DriverManager.getConnection(url, user, password);

        //3. 执行mysql语句
        String sql = "insert into jdbc values(4,'ise',20)";
        Statement statement = connection.createStatement();
        int i = statement.executeUpdate(sql);

        //4. 关闭资源
        statement.close();
        connection.close();
    }
}

#mysql.properties配置文件
#建议放在src文件夹下
#url=jdbc:mysql://ip:端口/数据库?rewriteBatchedStatements=true
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
#user=用户名
user=root
#password=密码
password=123456
#driver=对应数据库对应的Driver类
driver=com.mysql.jdbc.Driver

温馨提示:推荐用最后一种,灵活度比较高而且操作简单。


三、ResultSet(结果集)

基本介绍

        1. 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。

        2. ResultSet对象保持一个光标指向其当前数据行。最初,光标位于第一行之前。

        3. next 方法将光标移动到下一行,并且由于在ResultSet 对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集。

代码演示:

package JDBC.ResultSet;

import java.io.File;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class ResultSet01 {
    public static void main(String[] args) throws Exception {
        //准备工作
        Properties properties = new Properties();
        properties.load(new FileInputStream(new File("src//mysql.properties")));
        String url = properties.getProperty("url");
        String driver = properties.getProperty("driver");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        //1. loaded driver
        Class.forName(driver);

        //2. linked mysql
        Connection connection = DriverManager.getConnection(url, user, password);

        //3. do mysql_order
        PreparedStatement preparedStatement = connection.prepareStatement("select * from jdbc ");
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            System.out.println(resultSet.getInt(1) + "    " +
                    resultSet.getString(2) + "    " +
                    resultSet.getInt(3));
        }
        //4. close
        connection.close();
        preparedStatement.close();
        resultSet.close();

    }
}

四、Statement 和 PreparedStatement

Statement

        1. Statement 对象用于执行静态 SQL 语句并返回其生成的结果的对象。

        2. Statement 对象执行 SQL 语句,存在 SQL 注入风险。

        3. SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,恶意攻击数据库。

        4. 要防范 SQL 注入,只要用 PreparedStatement 取代 Statement 就可以了。

代码演示:

package JDBC.Statement;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

public class Statement01 {
    public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {
        //准备工作
        Properties properties = new Properties();
        properties.load(new FileInputStream("src//mysql.properties"));
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");

        String name = "1' or"; //
        String pwd = "or '1'= '1"; // 万能密码

        //加载Driver
        Class.forName(driver); // 可省略

        //获取mysql连接
        Connection connection = DriverManager.getConnection(url, user, password);

        //执行mysql命令
        Statement statement = connection.createStatement();

        //SQL注入 通过插入一些非法语句使得验证条件被屏蔽
        String sql = "select * from users where name ='"
                + user + "' and password = '" + pwd + "'";

        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()) {
            System.out.print(resultSet.getInt(1) + "\t");
            System.out.print(resultSet.getString(2) + "\t\t");
            System.out.println(resultSet.getString(3));
        }

        //关闭资源
        resultSet.close();
        statement.close();
        connection.close();
    }
}

PreparedStatement 

        1. PreparedStatement 执行的 SQL 语句中的参数用问号表示,调用PreparedStatement 对象的 setXxx() 方法来设置这些参数。setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从1 开始),第二个是设置的 SQL 语句中参数的值。

        2. 调用 executeQuery() ,执行查询操作,返回ResultSet对象

        3. 调用 executeUpdate() ,执行增,删,改操作。

        4. 使用预处理可以不再使用 + 拼接sql语句,减少语法错误,而且可以有效的解决了SQL注入问题,还能大大减少编译次数,效率较高。通常情况下,我们推荐使用PreparedStatement。

代码演示:

package JDBC.PreparedStatement;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

public class PStatement_02 {
    public static void main(String[] args) throws SQLException, IOException, ClassNotFoundException {
        //准备工作
        Properties properties = new Properties();
        properties.load(new FileInputStream("src//mysql.properties"));
        String url = properties.getProperty("url");
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");

        String name = "1' or"; //
        String pwd = "or '1'= '1"; // 万能密码

        //加载Driver
        Class.forName(driver); // 可省略

        //获取mysql连接
        Connection connection = DriverManager.getConnection(url, user, password);

        //执行mysql命令
        String sql = "select * from users where name = ? and password = ?";

        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        //在preparedStatement 调用setXxx()时会检查插入的语句,以此避免SQL注入问题
        preparedStatement.setString(1, name);
        preparedStatement.setString(2, pwd);

        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            System.out.print(resultSet.getInt(1) + "\t");
            System.out.print(resultSet.getString(2) + "\t\t");
            System.out.println(resultSet.getString(3));
        }//此时无输出

        //关闭资源
        resultSet.close();
        preparedStatement.close();
        connection.close();
    }
}


五、事务

基本介绍

        1. JDBC程序中当一个Connection 对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。

        2. JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务。

        3. 调用Connection的setAutoCommit(false)可以取消自动提交事务。

        4. 在所有的SQL语句都成功执行后,调用Connecttion的commit() 方法,提交事务。

        5. 在其中某个操作失败或者出现异常时,调用Connection的rollback() 方法,回滚事务,默认回滚到事务开始时,也可以自己设置保存点。

 代码演示:

package JDBC.Transaction;

import JDBC.JDBCUtils;

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

public class transaction_01 {
    public static void main(String[] args) throws SQLException {
        //由前面的学习过程我们能发现,在JDBC操作数据库时,
        //获得Connection连接和释放资源的操作是相同的
        //因此我们可以写一个工具类,专门用来做连接操作和关闭资源操作
 
        //调用 JDBCUtils 工具类获得连接
        Connection con = JDBCUtils.con();
        String create_Table = "create table account (id int,`name` varchar(33),money double)";
        String insert1 = "insert into account values(1,'mike',1000)";
        String insert2 = "insert into account values(2,'Alice',20000)";
        String money_sub = "update account set money = money - 100 where id = 1";
        String money_add = "update account set money = money + 100 where id = 2";
        PreparedStatement preparedStatement = null;

        try {
            preparedStatement = con.prepareStatement(create_Table);
            preparedStatement.execute();
            preparedStatement = con.prepareStatement(insert1);
            preparedStatement.executeUpdate();
            preparedStatement = con.prepareStatement(insert2);
            preparedStatement.executeUpdate();
            con.setAutoCommit(false);//开始事务
            preparedStatement = con.prepareStatement(money_sub);
            preparedStatement.executeUpdate();
//            int a = 1 / 0;
            preparedStatement = con.prepareStatement(money_add);
            preparedStatement.executeUpdate();
            con.commit();//所有操作完成,提交事务
        } catch (SQLException e) {
            try {
                con.rollback();//若有异常事务回滚到开始时
            } catch (SQLException ex) {
                throw new RuntimeException(ex);
            }
            throw new RuntimeException(e);
        } finally {
            //调用 JDBCUtils 工具类释放资源
            JDBCUtils.close(null, con, preparedStatement);
        }
    }
}

JDBCUtils工具类

        将获取连接和释放资源的过程封装成方法。

package JDBC;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {
    public static String url;
    public static String user;
    public static String password;
    public static String driver;
    
    //类加载时自动调用
    static {
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream("src//mysql.properties"));
            url = properties.getProperty("url");
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            driver = properties.getProperty("driver");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    //获得一个连接
    public static Connection con() {
        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    
    //关闭传入的资源,资源不存在则传入null
    public static void close(ResultSet resultSet, Connection connection, Statement statement) {

        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (connection != null) {
                connection.close();
            }
            if (statement != null) {
                statement.close();
            }


        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

}


六、批处理

基本介绍

        1. 当需要成批插入或者更新时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理,通常情况下要比单独提交处理更有效率。

        2. JDBC的批量处理语句包括下面方法:

                addBatch():添加需要批量处理的SQL语句或参数

                executeBatch():执行批量处理语句

                clearBatch():清空批处理包的语句

        3. JDBC 连接MySQL时,如果要使用批处理功能,需要在url中添加参数?rewriteBatchedStatements=true(切记切记)

        4. 批处理往往和PreparedStatement一起搭配使用,既能减少编译次数,又减少运行次数,效率大大提高。

代码演示:

package JDBC.Batch_;

import JDBC.JDBCUtils;
import org.junit.jupiter.api.Test;

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

public class Batch_01 {

    @Test
    // 传统方法执行5000句SQL指令
    public void m1() throws SQLException {
        Connection con = JDBCUtils.con();
        String sql = "insert into account values (?,?,?)";
        PreparedStatement preparedStatement = con.prepareStatement(sql);
        long begin = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            preparedStatement.setInt(1, i);
            preparedStatement.setString(2, "jack" + i);
            preparedStatement.setInt(3, 22);
            preparedStatement.executeUpdate();
        }
        long end = System.currentTimeMillis();
        System.out.println(end - begin);//耗时2281ms
        JDBCUtils.close(null, con, preparedStatement);
    }

    @Test
    //批处理执行5000句SQL语句
    public void m2() throws SQLException {
        Connection con = JDBCUtils.con();
        String sql = "insert into account values (?,?,?)";
        PreparedStatement preparedStatement = con.prepareStatement(sql);
        long begin = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {//执行5000次sql
            preparedStatement.setInt(1, i);
            preparedStatement.setString(2, "jack" + i);
            preparedStatement.setInt(3, 20);
            preparedStatement.addBatch();//往批处理包添加SQL语句
            if ((i + 1) % 1000 == 0) {//批处理包添加1000条SQL语句后
                preparedStatement.executeBatch();//执行该批处理包
                preparedStatement.clearBatch();//清空该批处理包
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(end - begin);//耗时51ms

        JDBCUtils.close(null, con, preparedStatement);
    }


}

七、数据库连接池

传统获取Connection问题分析

        1. 传统的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,再验证IP地址,用户名和密码(0.05s - 1s 时间)。需要数据库连接时,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。

        2. 每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将会导致数据库内存泄漏,最终将导致数据库重启。

        3. 传统获取连接方式,不能控制创建的连接数量,如连接过多,也可能导致内存泄漏,数据库崩溃。

        4. 为了解决传统开发中的数据库连接问题,可以采用数据库连接池技术。

数据库连接池种类

        JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现。

        常见的数据库连接池有下面几种。

        1. C3P0 数据库连接池,速度相对较慢,稳定性不错。

        2. DBCP 数据库连接池,速度相对C3P0较快,但不稳定。

        3. Proxool 数据库连接池,有监控连接池状态的功能,稳定性较C3P0差一点。

        4. BoneCP 数据库连接池,速度快。

        5. Druid(德鲁伊)数据库连接池,由阿里提供,集DBCP,C3P0,Proxool 优点于一身的数据库连接池。(后面主要介绍德鲁伊数据库连接池的使用)

Druid数据库连接池

准备工作:1.将 druid.jar 文件添加到lib目录(点击蓝色字体即可下载)

                  2. 右键选择 Add as Library

配置文件:1. 将下面配置信息存入 druid.properties 中

                  2. 将 druid.properties 存到 src 目录下

#配置文件,根据自己的具体需求设置
#driverClassName=对应数据库的驱动路径
driverClassName=com.mysql.jdbc.Driver
#url=jdbc:mysql://ip:端口/数据库?rewriteBatchedStatements=true
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
#username=你的用户名  password=对应的密码  
username=root
password=123456
#初始化连接数量
initialSize=20
#最小连接数量
minIdle=20
#最大连接数量
maxActive=50
#最大等待时间
maxWait=5000

代码演示:

package JDBC.Druid;

import JDBC.JDBCUtils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.junit.jupiter.api.Test;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

//传统连接数据库和通过数据池连接对比

public class Druid01 {
    @Test
    //连续连接数据库5000次,每次连接完不关闭
    //出现错误提示:Too many connections
    public void m1() {
        for (int i = 0; i < 5000; i++) {
            //错误信息
            // Data source rejected establishment of connection,
            // message from server: "Too many connections"
            Connection con = JDBCUtils.con();
        }
    }

    //连接5000次数据库,每次连接完都关闭
    @Test
    public void m2() throws SQLException {
        long l = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            Connection con = JDBCUtils.con();
            con.close();
        }
        long l1 = System.currentTimeMillis();
        System.out.println(l1 - l);//耗时4385ms
    }

    //使用druid连接池连接数据库
    //获取5000次连接
    @Test
    public void m3() throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src//druid.properties"));

        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        long l = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            Connection connection = dataSource.getConnection();
            connection.close();
        }
        long l1 = System.currentTimeMillis();
        System.out.println(l1 - l);//耗时311ms
    }

}
package JDBC.Druid;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Properties;

public class Druid011 {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src//druid.properties"));

        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        Connection connection = dataSource.getConnection();
        String sql = "select * from account";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        while (resultSet.next()) {
            System.out.print(resultSet.getInt(1) + "\t");
            System.out.print(resultSet.getString(2) + "\t");
            System.out.println(resultSet.getInt(3));
        }

        connection.close();
        resultSet.close();
        preparedStatement.close();
    }
}

JDBCUtilsByDruid工具类

        在JDBCUtils工具类的基础上,将基于Druid数据库连接池的获取连接和释放资源操作封装成方法。

package JDBC;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtilsByDruid {
    public static DataSource dataSource = null;
    public static Properties properties = null;


    static {
        try {
            properties = new Properties();
            properties.load(new FileInputStream("src//druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Connection getConnection() {
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static void close(ResultSet resultSet, Connection connection, Statement statement) {
        try {
            if (resultSet != null)
                resultSet.close();
            if (connection != null)
                connection.close();
            if (statement != null)
                statement.close();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}


八、Apache-DBUtils类库

基本介绍

        1. commons - dbutils 是Apache 组织提供的一个开源JDBC工具类库,它是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量。

        2. QueryRunner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查、批处理。

        3. ResultSetHandler接口:该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。其部分实现类如下:

【Java】学JDBC看这篇文章就够了—JDBC保姆级教程_第5张图片

  

使用DBUtils类库进行查询操作

        

 准备工作:

        1. 将 commons-dbutils.jar 文件添加到lib目录中(点击蓝色字体即可下载)

        2. 右键选择 Add as Library

package JDBC.Druid;

import JDBC.JDBCUtils;
import JDBC.JDBCUtilsByDruid;
import JDBC.student;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.jupiter.api.Test;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class Druid02 {


    @Test
    //传统思路
    public void test1() throws SQLException {

        Connection con = JDBCUtils.con();

        PreparedStatement preparedStatement = con.prepareStatement("select * from jdbc");

        ResultSet resultSet = preparedStatement.executeQuery();
        ArrayList students = new ArrayList<>();

        while (resultSet.next()) {
            int id = resultSet.getInt(1);
            String name = resultSet.getString(2);
            int age = resultSet.getInt(3);
            students.add(new student(id, name, age));
        }
        JDBCUtils.close(resultSet, con, preparedStatement);
        for (student student : students) {
            System.out.println(student);
        }


    }
    //使用DBUtils类库进行查询操作
    // 查询多行多列数据
    @Test
    public void m1() throws SQLException {
        Connection connection = JDBCUtilsByDruid.getConnection();
        QueryRunner queryRunner = new QueryRunner();
        List query = queryRunner.query(connection, "select * from jdbc",
                new BeanListHandler<>(student.class));
        /*
            注意:student类必须有无参构造器和 set 函数
            若无参构造器不存在,则无法实例化对象
            若set 不存在,则无法赋值,所有属性都会被赋一个默认值
        */
        System.out.println(query);

        JDBCUtilsByDruid.close(null, connection, null);
    }

    @Test
    //查询单行数据
    public void m2() throws SQLException {
        Connection connection = JDBCUtilsByDruid.getConnection();
        QueryRunner queryRunner = new QueryRunner();
        student query = queryRunner.query(connection, "select * from jdbc where id = 1",
                new BeanHandler<>(student.class));
        System.out.println(query);
        JDBCUtilsByDruid.close(null, connection, null);
    }

    @Test
    //返回单行单列数据
    public void m3() throws SQLException {
        Connection connection = JDBCUtilsByDruid.getConnection();
        QueryRunner queryRunner = new QueryRunner();
        Object query = queryRunner.query(connection, "select name from jdbc where id = 2", new ScalarHandler());
        System.out.println(query);
        JDBCUtilsByDruid.close(null, connection, null);
    }
}

使用DBUtils类库进行增删改操作

package JDBC.Druid;

import JDBC.JDBCUtilsByDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.jupiter.api.Test;

import java.sql.Connection;
import java.sql.SQLException;

public class Druid03 {
    //测试插入数据
    @Test
    public void m1() throws SQLException {
        Connection connection = JDBCUtilsByDruid.getConnection();

        QueryRunner queryRunner = new QueryRunner();
        int update = queryRunner.update(connection, "insert into jdbc values(4,'erson',45)");
        System.out.println(update > 0 ? "yes" : "no");
        JDBCUtilsByDruid.close(null, connection, null);
    }

    @Test
    //测试更改数据
    public void m2() throws SQLException {
        Connection connection = JDBCUtilsByDruid.getConnection();

        QueryRunner queryRunner = new QueryRunner();

        int update = queryRunner.update(connection, "update jdbc set name = 'Lihua' where id = 1 ");
        System.out.println(update > 0 ? "yes" : "no");
        JDBCUtilsByDruid.close(null, connection, null);
    }

    @Test
    //测试删除数据
    public void m3() throws SQLException {
        Connection connection = JDBCUtilsByDruid.getConnection();
        QueryRunner queryRunner = new QueryRunner();
        int update = queryRunner.update(connection, "delete from jdbc where id =4");
        System.out.println(update > 0 ? "yes" : "no");
        JDBCUtilsByDruid.close(null, connection, null);
    }
}


九、最后的话

✨  原创不易,还希望各位大佬支持一下


  点赞,你的认可是我创作的动力!


⭐️  收藏,你的青睐是我努力的方向!


✏️  评论,你的意见是我进步的财富!

你可能感兴趣的:(Java,数据库,java,mysql)