JDBC和连接池

大家好,我是小笙,我们学习了JavaSe基础和Mysql基础,自然而然我们需要通过JDBC和连接池来连接数据库和优化java程序操作数据库,以下是我的学习笔记


JDBC和连接池

JDBC

JDBC概述

java程序代码通过使用JDBC可以连接任何提供了JDBC驱动的数据库,从而完成对数据库的操作

image-20220405141547540

JDBC基本原理图

JDBC API就是图中的接口规范,它统一了java应用程序和数据库的连接等操作

image-20220405144420570

JDBC程序编写
  1. 注册驱动 - 加载Driver类
    • Driver :每个驱动程序类必须实现的接口
    • DriverManage :用于管理一组JDBC驱动程序的基本服务。
  2. 获取连接 - 得到Connection
  3. 执行增删改查 - 发送SQL语句给mysql数据库执行
  4. 释放资源 - 关闭相关的连接

连接数据库代码实现

// 方式一:静态加载
public static void main(String[] args) throws SQLException {
    // 1. 注册驱动 - 加载Driver类
    Driver driver = new Driver();

    // 2. 获取连接 - 得到Connection
    String url = "jdbc:mysql://localhost:3308/al_tair";
    // 将用户名和密码放入到Properties对象中
    Properties properties = new Properties();
    properties.setProperty("user","XXX"); // 用户
    properties.setProperty("password","XXXXXX"); // 密码
    Connection connect = driver.connect(url, properties);

    // 3. 执行增删改查 - 发送SQL语句给mysql数据库执行
    String sql = "insert into dog values(2,'steven')";
    // statement用于执行静态sql语句并返回其生成的结果对象,后面具体详讲
    Statement statement = connect.createStatement();
    int rows = statement.executeUpdate(sql); // 返回是否添加成功
    System.out.println(rows>0? "添加成功" : "添加失败");

    // 4. 释放资源 - 关闭相关的连接
    statement.close();
    connect.close();
}

// 方式二:动态加载
// 1. 注册驱动 - 使用反射加载Driver类
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
     // 1. 注册驱动 - 使用反射加载Driver类
     Class cls = Class.forName("com.mysql.jdbc.Driver");
     Driver driver = (Driver) cls.newInstance();

     // 2. 获取连接 - 得到Connection
     String url = "jdbc:mysql://localhost:3308/al_tair";
     // 将用户名和密码放入到Properties对象中
     Properties properties = new Properties();
     properties.setProperty("user","XXX"); // 用户
     properties.setProperty("password","XXXXXX"); // 密码
     Connection connect = driver.connect(url, properties);

     // 3. 执行增删改查 - 发送SQL语句给mysql数据库执行
     String sql = "insert into dog values(3,'marry')";
     // statement用于执行静态sql语句并返回其生成的结果对象
     Statement statement = connect.createStatement();
     int rows = statement.executeUpdate(sql); // 返回是否添加成功
     System.out.println(rows>0? "添加成功" : "添加失败");

     // 4. 释放资源 - 关闭相关的连接
     statement.close();
     connect.close();
 }

// 方式三:DriverManage 
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, SQLException {
    // 1. 注册驱动 - 加载Driver类 - DriverManage :用于管理一组JDBC驱动程序的基本服务
    Class cls = Class.forName("com.mysql.jdbc.Driver");
    Driver driver = (Driver) cls.newInstance();
    String url = "jdbc:mysql://localhost:3308/al_tair";
    String root = "XXX";
    String pwd = "XXXXXX";
    // 注册驱动
    DriverManager.registerDriver(driver);

    // 2. 获取连接 - 得到Connection
    Connection connection = DriverManager.getConnection(url, root, pwd);

    // 3. 执行增删改查 - 发送SQL语句给mysql数据库执行
    String sql = "insert into dog values(4,'tony')";
    // statement用于执行静态sql语句并返回其生成的结果对象
    Statement statement = connection.createStatement();
    int rows = statement.executeUpdate(sql); // 返回是否添加成功
    System.out.println(rows>0? "添加成功" : "添加失败");

    // 4. 释放资源 - 关闭相关的连接
    statement.close();
    connection.close();
}

// 方式四:方式三的简化版(推荐)
/*
Driver 原码分析:注册Driver在静态代码块中已经实现
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }
    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}
*/
public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException, SQLException {
    Class cls = Class.forName("com.mysql.jdbc.Driver");
    String url = "jdbc:mysql://localhost:3308/al_tair";
    String root = "XXX";
    String pwd = "XXXXXX";

    // 1. 获取连接 - 得到Connection
    Connection connection = DriverManager.getConnection(url, root, pwd);

    // 2. 执行增删改查 - 发送SQL语句给mysql数据库执行
    String sql = "insert into dog values(5,'jack')";
    // statement用于执行静态sql语句并返回其生成的结果对象
    Statement statement = connection.createStatement();
    int rows = statement.executeUpdate(sql); // 返回是否添加成功
    System.out.println(rows > 0 ? "添加成功" : "添加失败");

    // 3. 释放资源 - 关闭相关的连接
    statement.close();
    connection.close();
}

// 方式五:mysql5.1.6可以无需手动反射Driver类,会自动调用驱动jar下的驱动包
public static void main(String[] args) throws SQLException {
    String url = "jdbc:mysql://localhost:3308/al_tair";
    String root = "root";
    String pwd = "luo1234567";

    // 1. 获取连接 - 得到Connection
    Connection connection = DriverManager.getConnection(url, root, pwd);

    // 2. 执行增删改查 - 发送SQL语句给mysql数据库执行
    String sql = "insert into dog values(6,'son')";
    // statement用于执行静态sql语句并返回其生成的结果对象
    Statement statement = connection.createStatement();
    int rows = statement.executeUpdate(sql); // 返回是否添加成功
    System.out.println(rows > 0 ? "添加成功" : "添加失败");

    // 3. 释放资源 - 关闭相关的连接
    statement.close();
    connection.close();
}

image-20220405172744703

使用配置文件读入来连接数据库

// Properties.properties
root = root
pwd = XXXXXX
url = jdbc:mysql://localhost:3308/al_tair
driver = com.mysql.jdbc.Driver
    
// package com.Al_tair.connectMySql.myJDBC;
public class JdbcDemo6 {
    public static void main(String[] args) throws IOException, SQLException {
        Properties properties = new Properties();
        String filePath = "E:\\Java_training\\Java_code\\JavaIdea03\\java\\Javase_HSping\\src\\com\\Al_tair\\connectMySql\\myJDBC\\Properties.properties";
        properties.load(new FileInputStream(filePath));
        String url = properties.getProperty("url");
        String root = properties.getProperty("root");
        String pwd = properties.getProperty("pwd");
        // 1. 获取连接 - 得到Connection
        Connection connection = DriverManager.getConnection(url, root, pwd);

        // 2. 执行增删改查 - 发送SQL语句给mysql数据库执行
        String sql = "insert into dog values(7,'Jason')";
        // statement用于执行静态sql语句并返回其生成的结果对象
        Statement statement = connection.createStatement();
        int rows = statement.executeUpdate(sql); // 返回是否添加成功
        System.out.println(rows > 0 ? "添加成功" : "添加失败");

        // 3. 释放资源 - 关闭相关的连接
        statement.close();
        connection.close();
    }
}
// 拓展:如果用idea编译器无法正确使用相对路径,检查:Run -> Edit Configurations -> 选中对应java程序修改Working directory,该地址就是相对位置的起点;如果不会就使用全路径

Statement

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

在业务中,我们一般不使用Statement对象对数据库(存在SQL注入的风险:利用某些系统没有对用户输入的数据及逆行充分的过滤,注入非法的SQL语句,恶意攻击数据库)

进而我们使用 PrepareStatement(预处理,主要使用这个),CallableSatement(可以处理数据库的存储过程)

// PrepareStatement 讲解
// ? 占位符 可以通过set语句填充,如下图
String sql = "SELECT *FROM emp WHERE username = ? AND password = ?";
// 预处理的好处
// 1. 不再使用 + 拼接sql语句,减少语法错误
// 2. 有效的解决了sql注入问题
// 3. 大大减少了编译次数,效率较高

// executeUpdate() 方法无需再填入sql语句
public static void main(String[] args) throws IOException, SQLException {
    String admin_name = "";
    String admin_pwd = "";

    // 读取配置文件
    Properties properties = new Properties();
    String filePath = "src\\com\\Al_tair\\connectMySql\\myJDBC\\Properties.properties";
    properties.load(new FileInputStream(filePath));
    String url = properties.getProperty("url");
    String root = properties.getProperty("root");
    String pwd = properties.getProperty("pwd");
    // 1. 获取连接 - 得到Connection
    Connection connection = DriverManager.getConnection(url, root, pwd);

    // 2. 执行增删改查 - 发送SQL语句给mysql数据库执行
    String sql = "select `name`,pwd from admin where name = ? and pwd = ? ";
    // preparedStatement用于执行静态sql语句并返回其生成的结果对象
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    preparedStatement.setString(1,admin_name);
    preparedStatement.setString(2,admin_pwd);

    int rows = preparedStatement.executeUpdate();
    System.out.println(rows> 0 ? "成功" : "失败");
    // 3. 释放资源 - 关闭相关的连接
    preparedStatement.close();
    connection.close();
}

image-20220406141403921

ResultSet(结果集)

概念:表示数据库结果集的数据表(通常通过执行查询数据库语句执行)

ResultSet对象保持一个光标指向当前的数据行,光标从第一行开始向下遍历,如果没有更多行的时候将会返回false,迭代器的用法

public class ResultSetDemo1 {
    public static void main(String[] args) throws IOException, SQLException {\
        // 读取配置文件
        Properties properties = new Properties();
        String filePath = "src\\com\\Al_tair\\connectMySql\\myJDBC\\Properties.properties";
        properties.load(new FileInputStream(filePath));
        String url = properties.getProperty("url");
        String root = properties.getProperty("root");
        String pwd = properties.getProperty("pwd");
        // 1. 获取连接 - 得到Connection
        Connection connection = DriverManager.getConnection(url, root, pwd);

        // 2. 执行增删改查 - 发送SQL语句给mysql数据库执行
        String sql = "select *from dog";
        // statement用于执行静态sql语句并返回其生成的结果对象
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()){
            int index = 1;
            int id = resultSet.getInt(index++); // 获取第一列
            String name = resultSet.getString(index); // 获取第二列
            System.out.println("id: "+ id + "  name: "+name);
        }

        // 3. 释放资源 - 关闭相关的连接
        resultSet.close();
        statement.close();
        connection.close();
    }
}

image-20220405203403926

JDBC API梳理

image-20220406151018088

JDBC自定义工具类

为了减少代码复用性,我们添加工具类来实现连接和关闭

public class JDBCUtils {
    private static String user; // 用户名
    private static String password; // 密码
    private static String url; // url

    static {
        String filePath = "E:\\Java_training\\Java_code\\JavaIdea03\\java\\Javase_HSping" +
                "\\src\\com\\Al_tair\\connectMySql\\utils\\Properties.properties";
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream(filePath));
            user = properties.getProperty("root");
            password = properties.getProperty("pwd");
            url = properties.getProperty("url");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    
    // 连接数据库
    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }
    
    // 查询语句关闭
    public static void closeQueryConnection(ResultSet rst, Statement statement,Connection connection){
        try {
            rst.close();
            statement.close();
            connection.close();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }

    // dml语句操作关闭
    public static void closeDmlConnection(Statement statement,Connection connection){
        try {
            statement.close();
            connection.close();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }
}

操作数据库的事务

概念:创建Connection默认是自动提交事务,每次执行sql语句都会默认自动提交commit,不能发生回滚

image-20220406183335392

image-20220406183304922

image-20220406183318359

批处理

作用:用来一次性插入多条sql语句,提高插入效率

JDBC批量处理(PreparedStatement接口)方法如下

PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.addBatch(); // 增加批处理数据
preparedStatement.executeBatch(); // 进行批处理
preparedStatement.clearBatch(); // 清空批处理

image-20220406184343391

注意:JDBC连接Mysql时候,如果要使用批处理功能,必须在url路径中添加如下语句,并且往往和PreparedStatement一起使用,不仅减少编译次数,也可以减少运行次数,效率大大提高

// 添加?rewriteBatchedStatements=true语句
root = xxxx
pwd = xxxxxxxx
url = jdbc:mysql://localhost:3308/al_tair?rewriteBatchedStatements=true

测试代码(批量处理大大减少时间)

// 批处理底层数据就是存放在ArrayList集合中batchedArgs对象数组中
public class BatchDemo {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        // ? 占位符
        String sql = "insert into admin values(?,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            preparedStatement.setInt(1,i);
            preparedStatement.setString(2,"jack"+i);
            preparedStatement.setString(3,"123456"+i);
            preparedStatement.addBatch();
            if((i+1)%1000 == 0) {
                // 批量处理1000条
                preparedStatement.executeBatch();
                preparedStatement.clearBatch();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(end - start);
        JDBCUtils.closeDmlConnection(connection,preparedStatement);
    }
}

// 源码
public void addBatch() throws SQLException {
    synchronized(this.checkClosed().getConnectionMutex()) {
        if (this.batchedArgs == null) {
            this.batchedArgs = new ArrayList();
        }

        for(int i = 0; i < this.parameterValues.length; ++i) {
            this.checkAllParametersSet(this.parameterValues[i], this.parameterStreams[i], i);
        }
        this.batchedArgs.add(new PreparedStatement.BatchParams(this.parameterValues, this.parameterStreams, this.isStream, this.streamLengths, this.isNull));
    }
}

连接池

概念:数据库连接池主要负责分配,管理和释放数据库的连接

image-20220407194331691

常见的数据库连接池(现在常用C3P0,Druid)

  • C3P0连接池,速度相对慢,但是稳定性不错(hibernate,spring)
  • DBCP连接池,速度相对比C3P0快,但是稳定性不好不常用
  • Proxool连接池,有监控连接池状态的功能,但是稳定性没有C3P0好
  • BoneCP连接池,速度快(不常用)
  • Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP,C3P0,Proxool优点于一身

C3P0连接池

我们接下来讲的主要是C3P0连接池,首先引入jar包

image-20220407200446550 下载地址

详细说明 Data Source

image-20220407222707755

方式一:自己传入配置参数

// ComboPooledDataSource 实现了DataSource接口
public class C3P0Demo {
    public static void main(String[] args) throws PropertyVetoException, SQLException {
        // 创建连接池
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();

        String filePath = "E:\\Java_training\\Java_code\\JavaIdea03\\java\\Javase_HSping" +
                "\\src\\com\\Al_tair\\connectMySql\\utils\\Properties.properties";
        Properties properties = new Properties();
        String user,password,url,driver;
        try {
            properties.load(new FileInputStream(filePath));
            user = properties.getProperty("root");
            password = properties.getProperty("pwd");
            url = properties.getProperty("url");
            driver = properties.getProperty("driver");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 给连接池 comboPooledDataSource 设置参数
        comboPooledDataSource.setDriverClass(driver);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setJdbcUrl(url);

        // 初始化连接数
        comboPooledDataSource.setInitialPoolSize(10); // 初始化连接数
        comboPooledDataSource.setMaxPoolSize(30); // 最大连接数,超过30个将进入等待队列
        // 连接
        Connection connection = comboPooledDataSource.getConnection();
        System.out.println("----------");
        // 关闭连接
        connection.close();
    }
}

方式二:通过xml配置文件配置

<!-- c3p0-config.xml配置文件 注意:要将xml配置文件放在src -->
<c3p0-config>
<!--    数据源名称   -->
  <named-config name="DataSource">
<!-- 驱动类 -->
  <property name="driverClass">com.mysql.jdbc.Driver</property>
  <!-- url-->
  	<property name="jdbcUrl">jdbc:mysql://localhost:3308/al_tair</property>
  <!-- 用户名 -->
  		<property name="user">root</property>
  		<!-- 密码 -->
  	<property name="password">luo1234567</property>
  	<!-- 每次增长的连接数-->
    <property name="acquireIncrement">5</property>
    <!-- 初始的连接数  -->
    <property name="initialPoolSize">10</property>
    <!-- 最小连接数 -->
    <property name="minPoolSize">5</property>
   <!-- 最大连接数 -->
    <property name="maxPoolSize">50</property>

	<!-- 可连接的最多的命令对象数 -->
    <property name="maxStatements">5</property> 
    
    <!-- 每个连接对象可连接的最多的命令对象数 -->
    <property name="maxStatementsPerConnection">2</property>
  </named-config>
</c3p0-config>
// 测试代码
public class C3P0Demo2 {
    public static void main(String[] args) throws SQLException {
        // 通过配置文件获取连接数据库的信息
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("DataSource");
        // 获取连接
        Connection connection = comboPooledDataSource.getConnection();
        System.out.println("-------");
        // 关闭连接
        connection.close();
    }
}

Druid连接池

Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP,C3P0,Proxool优点于一身,连接速度快

druid配置类

#key=value
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3308/al_tair?rewriteBatchedStatements=true
username=root
password=XXXXXXX
#initial connection Size
initialSize=10
#min idle connecton size
minIdle=5
#max active connection size
maxActive=50
#max wait time (5000 mil seconds)
maxWait=5000

德鲁伊连接池工具类

public class JDBCUtilsByDruid {
    private static DataSource dataSource;

    static {
        String filePath = "E:\\Java_training\\Java_code\\JavaIdea03\\java\\Javase_HSping\\" +
                "src\\com\\Al_tair\\connectMySql\\druid\\druid.properties";
        Properties properties = new Properties();
        try {
            properties.load(new FileInputStream(filePath));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 连接数据库
    public static Connection getConnection(){
        try {
            // 创建一个指定参数的数据库连接池(德鲁伊连接池)
            return dataSource.getConnection();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }

    // 查询语句关闭
    public static void closeQueryConnection(Connection connection, Statement statement, ResultSet rst){
        try {
            rst.close();
            statement.close();
            connection.close();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }

    // dml语句操作关闭
    public static void closeDmlConnection(Connection connection,Statement statement){
        try {
            statement.close();
            connection.close();
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables);
        }
    }

    public static void closeConnection(Connection connection){
        try {
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

测试类

public class DruidDemo {
    public static void main(String[] args) throws Exception {
        Connection connection = JDBCUtilsByDruid.getConnection();
        System.out.println("连接成功");
        JDBCUtilsByDruid.closeConnection(connection);
    }
}

Apache - DBUtils

引出原因:

  • resultSet合connection是关联的,如果关闭连接,就不能再使用resultSet
  • resultSet来获取信息读取也不太方便,不利于数据管理

解决思路: 将数据库表中的每条记录用对象的形式(通常称作JavaBean,PoJo),Domain) 保存在集合ArrayList中

自己模拟源码测试代码

// 取出核心代码分析
ArrayList<Dog> list = new ArrayList<>();
while (resultSet.next()){
    int index = 1;
    // 以下四行就是一个记录
    int id = resultSet.getInt(index++); // 获取第一列
    String name = resultSet.getString(index++); // 获取第二列
    String color = resultSet.getString(index++); // 获取第三列
    Date birth = resultSet.Date(index++); // 获取第四列
    list.add(new Dog(id,name,color,birth)); // 将resultSet取出来放入到集合数组中
}

public class Dog {
    private int id;
    private String name;
    private String color;
    private Date birth;
    public Dog() {}
    public Dog(int id, String name, String color, Date birth) {
        this.id = id;
        this.name = name;
        this.color = color;
        this.birth = birth;
    }
}

Dog表如下

image-20220408200441178

Apache - DBUtils工具的使用

首先需要导入jar包 commons-dbutils-1.3.jar

commons_dbutils是Apache组织提供的一个开源的JDBC工具类库

方法作用
ArrayHandler把结果集中的第一行数据转成对象数组
ArrayListHandler把结果集中的每一行数据都转成一个数组,再存放到Lisr中
BeanHandler把结果集中的每一行数据封装到一个对应的javaBean实例中
BeanListHandler将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里
ColumnListHandler将结果集中某一列的数据存放到List中
KeyedHandler(name)将结果集中的每行数据都封装到Map里,再把这些map再存到一个map里,其key为指定的key
MapHandler将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值
MapListHandler将结果集中的每一行数据都封装到一个Map里,然后再存放到List
ScalarHandler将结果集中的某一行某一列的数据存放到Object对象中

查询语句

public static void main(String[] args) throws SQLException {
    // 得到连接
    Connection connection = JDBCUtilsByDruid.getConnection();
    // 创建QueryRunner
    QueryRunner queryRunner = new QueryRunner();
    String sql = "SELECT *FROM dog";
    // connection 连接 sql 操作语句 new BeanListHandler<>(Dog.class) 通过得到Dog类,进行反射封装成对象
    List<Dog> list = queryRunner.query(connection, sql, new BeanListHandler<>(Dog.class));
    for (Dog dog:list
        ) {
        System.out.println(dog);
    }
    JDBCUtilsByDruid.closeConnection(connection);
}

// 源码剖析 queryRunner 的 query方法
// connection 连接 sql 操作语句 new BeanListHandler<>(Dog.class) 通过得到Dog类,进行反射封装成对象 params 用来传入替代?占位符的数据
public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
    PreparedStatement stmt = null;
    ResultSet rs = null;
    Object result = null;

    try {
        // 创建预处理  PreparedStatement
        stmt = this.prepareStatement(conn, sql);
        // fillStatement(stmt, params) 主要是用于解决替换sql语句中?占位符
        this.fillStatement(stmt, params);
        // 得到结果集 resultSet
        rs = this.wrap(stmt.executeQuery());
        // 返回的 resultSet --> rsh对象 存储到ArrayList集合中
        result = rsh.handle(rs);
    } catch (SQLException var33) {
        this.rethrow(var33, sql, params);
    } finally {
        try {
            // 关闭结果集
            this.close(rs);
        } finally {
            // 关闭PreparedStatement
            this.close((Statement)stmt);
        }
    }

    return result;
}

dml操作

// 测试删除语句,其他dml语句大同小异
public class DBUtilsDmlDemo {
    public static void main(String[] args) throws SQLException {
        // 建立连接
        Connection connection = JDBCUtilsByDruid.getConnection();
        // 创建 QueryRunner
        QueryRunner queryRunner = new QueryRunner();
        String sql = "DELETE FROM dog WHERE ID = ?";
        // update方法能统一处理增删改操作 返回的是影响的行数:0表示数据库中的表没有受到影响
        int deleteVictory = queryRunner.update(connection, sql, 1);
        System.out.println(deleteVictory > 0?"删除成功":"删除失败");
        JDBCUtilsByDruid.closeConnection(connection);
    }
}

// 源码如下
public int update(Connection conn, String sql, Object... params) throws SQLException {
    PreparedStatement stmt = null;
    int rows = 0;
    try {
        stmt = this.prepareStatement(conn, sql);
        this.fillStatement(stmt, params);
        rows = stmt.executeUpdate();
    } catch (SQLException var10) {
        this.rethrow(var10, sql, params);
    } finally {
        this.close((Statement)stmt);
    }

    return rows;
}

BasicDao

概念:专门和数据交互,完成对数据库的CRUD操作

image-20220409210413206

测试Dog表代码

// BasicDao.java
public class BasicDao<T> {
    private QueryRunner qr = new QueryRunner();

    // dml操作语句
    public int DmlUpdate(String sql,Object...params){
        Connection connection = null;

        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.update(connection,sql,params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtilsByDruid.closeConnection(connection);
        }
    }

    // 查询语句:返回集合(表)
    public List<T> SelectMultiLine(String sql, Class<T> cls, Object...params){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection,sql,new BeanListHandler<T>(cls),params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtilsByDruid.closeConnection(connection);
        }
    }

    // 查询语句:返回单行数据
    public T SelectSingleLine(String sql, Class<T> cls, Object...params){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection,sql,new BeanHandler<T>(cls),params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtilsByDruid.closeConnection(connection);
        }
    }

    // 查询语句:返回某行某列数据
    public Object SelectSingleLine(String sql, Object...params){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection,sql,new ScalarHandler(),params);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JDBCUtilsByDruid.closeConnection(connection);
        }
    }
}

// DogDao.java
public class DogDao extends BasicDao<Dog> {}

// TestDog.java
public class TestDog {
    public static void main(String[] args) {
        DogDao dogDao = new DogDao();

        // dml操作测试
        String sql = "insert into dog values(3,'marry','blue',?)";
        int rows = dogDao.DmlUpdate(sql, "2021-3-19");
        System.out.println(rows > 0?"测试成功":"未添加数据到数据库'");

        // 查询表
        sql = "select *from dog where id = ?";
        Object o = dogDao.SelectSingleLine(sql, Dog.class, 2);
        System.out.println(o);
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Al_tair

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值