4

一起学Java——JDBC

 2 years ago
source link: https://blog.csdn.net/k1507157/article/details/122367217
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一起学Java——JDBC

专业bug开发 2022-01-08 22:37:38 3147
专栏收录该内容
10 篇文章 1 订阅

学习Java的对于JDBC肯定不会陌生。Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。

测试使用JDBC

相关操作建议参照!!!
参考文章链接

  1. 新建项目结构如下,引入jar包到lib文件下;
    请添加图片描述

  2. 设置jar包到项目环境;
    在这里插入图片描述
    请添加图片描述

  3. 数据库新建study数据库,并在该数据库下新建student表;
    请添加图片描述

  4. 编写测试类代码如下;


import java.sql.*;

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-07 16:29
 */
public class JdbcExample {
//    MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
//    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
//    static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB";

//     MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost:3306/study?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";


    // 数据库的用户名与密码,需要根据自己的设置
    static final String USER = "root";
    static final String PASS = "123456";

    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        try {
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);

            // 打开链接
            System.out.println("连接数据库...");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);

            // 执行查询
            System.out.println(" 实例化Statement对象...");
            stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM student");

            // 展开结果集数据库
            while (rs.next()) {
            //rs.next()返回布尔值,代表是否存在下一条记录
            //如果有,返回true。继续提取下一条记录
            //如果没有,返回false,结束循环
                // 通过字段检索
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String classname = rs.getString("classname");

                // 输出数据
                System.out.print("ID: " + id);
                System.out.print(", 姓名: " + name);
                System.out.print(", 班级: " + classname);
                System.out.print("\n");
            }
            // 完成后关闭
            rs.close();
            stmt.close();
            conn.close();
        } catch (SQLException se) {
            // 处理 JDBC 错误
            se.printStackTrace();
        } catch (Exception e) {
            // 处理 Class.forName 错误
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException se2) {
            }// 什么都不做
            try {
                if (conn != null)
                    conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
        System.out.println("Goodbye!");
    }
}

  1. 测试代码运行结果如下;
    请添加图片描述

预编译语句集防止SQL注入

  1. 首先我们明确一下什么是SQL注入。百度百科的解释如下:

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

  1. SQL注入测试,在查询语句后面拼接1=1,例如;
# 原本查询语句
SELECT * FROM student where classname = '" + cname + "'

# SQL注入后的语句
cname = ' or 1=1 or 1='

SELECT * FROM student where classname = '' or 1=1 or 1=''

  1. 使用预编译语句集防止SQL注入,实现逻辑如下;

import java.sql.*;
import java.util.Scanner;

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-07 16:29
 */
public class JdbcExample {
//    MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
//    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
//    static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB";

//     MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost:3306/study?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";


    // 数据库的用户名与密码,需要根据自己的设置
    static final String USER = "root";
    static final String PASS = "123456";

    public static void main(String[] args) {
        Connection conn = null;
//        Statement stmt = null;
        PreparedStatement pstmt = null;
        try {
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);

            // 打开链接
            System.out.println("连接数据库...");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);

            // 执行查询
            System.out.println(" 实例化Statement对象...");
            System.out.println("请输入待查询的班级:");

//            仔细看这部分代码,prepareStatement对sql进行了预编译
            Scanner in = new Scanner(System.in);
            String cname = in.next();
            String sql= "SELECT * FROM student where classname = ?";
            pstmt= conn.prepareStatement(sql);
            
            // 使用setString()设置参数
            pstmt.setString(1, cname);
            ResultSet rs = pstmt.executeQuery();
            
            
            
            // 展开结果集数据库
            while (rs.next()) {
                // 通过字段检索
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String classname = rs.getString("classname");

                // 输出数据
                System.out.print("ID: " + id);
                System.out.print(", 姓名: " + name);
                System.out.print(", 班级: " + classname);
                System.out.print("\n");
            }
            // 完成后关闭
            rs.close();
            pstmt.close();
            conn.close();
        } catch (SQLException se) {
            // 处理 JDBC 错误
            se.printStackTrace();
        } catch (Exception e) {
            // 处理 Class.forName 错误
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (pstmt != null) pstmt.close();
            } catch (SQLException se2) {
            }// 什么都不做
            try {
                if (conn != null)
                    conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
        System.out.println("Goodbye!");
    }
}

封装使用DbUtils工具类

  1. 为什么需要封装这么一个类?

观察上面的代码,我们每进行一次数据库的操作就需要进行数据库的五项操作,代码内聚度不够高,当我们对这一段相同作用的代码进行封装,形成一个工具类,就可以完美解决代码多次重复的问题。

  1. 在我们的项目下新建一个包,存放公共类;请添加图片描述
  2. 工具类代码编写如下,详细原理参见注释;
package com.five.jdbc.common;

import java.sql.*;

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 10:52
 */
public class DbUtils {
    //MySQL 8.0 以上版本-JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost:3306/study?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
    //数据库的用户名与密码
    static final String USER = "root";
    static final String PASS = "123456";

    /**
     * @Description: 创建数据库连接
     * @Param:
     * @return: 返回连接
     */
    public static Connection getConnection() throws ClassNotFoundException, SQLException {
        // 注册 JDBC 驱动
        Class.forName(JDBC_DRIVER);
        // 打开链接
        Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
        return conn;
    }

    /**
     * @Description: 关闭连接,释放资源
     * @Param: rs-结果集对象, stmt-Statement对象,  conn-Connection对象
     */
    public static void closeConnection(ResultSet rs, Statement stmt, Connection conn) throws SQLException {
        // 关闭rs-结果集对象
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 关闭stmt-Statement对象
        try {
            if (stmt != null) {
                stmt.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 关闭conn-Connection对象
        try {
            if (conn != null && !conn.isClosed()) {
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  1. 使用工具类操作数据,新建类如下,原理参照注释;
    请添加图片描述
package com.five.jdbc.example;

import com.five.jdbc.common.DbUtils;

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

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 13:06
 */
public class InsertExample{
    public static void main(String[] args) throws SQLException {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入学生编号:");
        int id = in.nextInt();
        System.out.println("请输入学生姓名:");
        String name = in.next();
        System.out.println("请输入学生班级:");
        String cname = in.next();

        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = DbUtils.getConnection();
            String sql = "insert into student(id,name,classname) values(?,?,?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);
            pstmt.setString(2, name);
            pstmt.setString(3, cname);
            int cnt  = pstmt.executeUpdate();   //写操作影响的行数
            System.out.println("cnt" + cnt);
            System.out.println(name = "添加成功啦!");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {
            DbUtils.closeConnection(null, pstmt, conn);
        }
    }
}

请添加图片描述

package com.five.jdbc.example;

import com.five.jdbc.common.DbUtils;

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

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 13:27
 */
public class UpdateExample {
    public static void main(String[] args) throws SQLException {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入学生编号:");
        int id = in.nextInt();
        System.out.println("请输入学生班级:");
        String cname = in.next();

        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = DbUtils.getConnection();
            String sql = "update student set classname=? where id=?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, cname);
            pstmt.setInt(2, id);

            int cnt  = pstmt.executeUpdate();   //写操作影响的行数

            if(cnt == 1){
                System.out.println("学生班级调整完毕!");
            }else{
                System.out.println("没有找到对应编号学生!");
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {
            DbUtils.closeConnection(null, pstmt, conn);
        }
    }
}

请添加图片描述

package com.five.jdbc.example;

import com.five.jdbc.common.DbUtils;

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

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 13:37
 */
public class DeleteExample {
    public static void main(String[] args) throws SQLException {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入学生编号:");
        int id = in.nextInt();

        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = DbUtils.getConnection();
            String sql = "delete from student where id=?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);

            int cnt = pstmt.executeUpdate();   //写操作影响的行数

            if (cnt == 1) {
                System.out.println("学生信息删除完毕!");
            } else {
                System.out.println("没有找到对应编号学生!");
            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            DbUtils.closeConnection(null, pstmt, conn);
        }
    }
}

请添加图片描述

JDBC事务管理

  1. 什么是事务?

事务是以一种可靠的、一致的方式,访问和操作数据库的程序单元

通俗的说:要么把事情做完,要么什么都不做,不要做一半。

  1. 事务原理图如下;

在这里插入图片描述

在这里插入图片描述

  1. 提交事务模式
  • 自动提交事务

每执行一次写操作,自动提交事务
自动提交开启方法:conn.setAutoCommit(true)
自动事务是JDBC的默认行为,此模式无法保证数据一致性

  • 手动提交事务

显示调用commit()和rollback()方法管理事务
手动提交开启方法:conn.setAutoCommit(false)
保证多数据一致性,但必须手动调用提交/回滚方法

手动调用事务案例:
请添加图片描述

package com.five.jdbc.example;

import com.five.jdbc.common.DbUtils;

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

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 16:02
 */
public class TransactionExample {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            conn = DbUtils.getConnection();
            conn.setAutoCommit(false);   //关闭自动提交
            String sql = "insert into student(id,name,classname) values(?,?,?)";
            for (int i = 20; i < 40; i++) {
//                模拟发生异常的情况
//                if(i == 35){
//                    throw new RuntimeException("添加失败");
//                }
                pstmt = conn.prepareStatement(sql);
                pstmt.setInt(1, i);
                pstmt.setString(2, "学生" + i);
                pstmt.setString(3, "高三(10)班");
                pstmt.executeUpdate();   //写操作
            }
            conn.commit(); //提交数据
        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (conn != null && !conn.isClosed()) {
                    conn.rollback();   //如果发生异常,数据库事务回滚
                }
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
            DbUtils.closeConnection(null, pstmt, conn);
        }
    }
}

实体类实现分页数据封装

设想一下实际的开发,我们查询数据经常是一组数据,这一组数据我们需要统一返回,这时候我们可以利用Java面向对象的特性进行处理。

  1. 新建实体类和测试类;
    请添加图片描述
  2. 实体类代码;
package com.five.jdbc.entity;

/**
 * Description:学生信息实体类
 *   1.具备默认构造函数  2.属性私有   3.存在getter和setter
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 16:19
 */
public class Student {
    public Student(){

    }
    private Integer id;
    private String name;
    private String cname;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }


}

  1. 测试类代码,原理参见注释;
    请添加图片描述
package com.five.jdbc.example;

import com.five.jdbc.common.DbUtils;
import com.five.jdbc.entity.Student;

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

/**
 * Description:分页查询
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 16:28
 */
public class PaginationExample {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入页号:");
        int page = in.nextInt();

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        
        // 用于存放结果的list
        List<Student> list = new ArrayList<>();
        try {
            conn = DbUtils.getConnection();
            String sql = "select * from student limit ?,10";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, (page-1)*10);
            rs = pstmt.executeQuery();
            // 展开结果集数据库
            while (rs.next()) {
                // 通过字段检索
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String classname = rs.getString("classname");

                // 数据保存到实体类中
                Student stu = new Student();
                stu.setId(id);
                stu.setName(name);
                stu.setCname(classname);
                list.add(stu);
            }
            System.out.println(list.size());
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }
}

JDBC中Date日期对象的处理

  1. 数据表新增日期字段;
    请添加图片描述
  2. 获取数据表日期;
 //JDBC获取日期的时候使用java.sql.Date,继承于java.util.Date
Date sdate = rs.getDate("sdate");
package com.five.jdbc.example;

import java.sql.*;
import java.util.Scanner;

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-07 16:29
 */
public class JdbcExample {
//    MySQL 8.0 以下版本 - JDBC 驱动名及数据库 URL
//    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
//    static final String DB_URL = "jdbc:mysql://localhost:3306/RUNOOB";

//     MySQL 8.0 以上版本 - JDBC 驱动名及数据库 URL
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost:3306/study?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";


    // 数据库的用户名与密码,需要根据自己的设置
    static final String USER = "root";
    static final String PASS = "123456";

    public static void main(String[] args) {
        Connection conn = null;
//        Statement stmt = null;
        PreparedStatement pstmt = null;
        try {
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);

            // 打开链接
            System.out.println("连接数据库...");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);

            // 执行查询
            System.out.println(" 实例化Statement对象...");
            System.out.println("请输入待查询的班级:");

//            仔细看这部分代码,prepareStatement对sql进行了预编译
            Scanner in = new Scanner(System.in);
            String cname = in.next();
            String sql= "SELECT * FROM student where classname = ?";
            pstmt= conn.prepareStatement(sql);
            pstmt.setString(1, cname);
            ResultSet rs = pstmt.executeQuery();



//             展开结果集数据库
            while (rs.next()) {
                // 通过字段检索
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String classname = rs.getString("classname");

                //JDBC获取日期的时候使用java.sql.Date,继承于java.util.Date
                Date sdate = rs.getDate("sdate");
                // 输出数据
                System.out.print("ID: " + id);
                System.out.print(", 姓名: " + name);
                System.out.print(", 班级: " + classname);
                System.out.print(", 日期: " + sdate);
                System.out.print("\n");
            }
            // 完成后关闭
            rs.close();
            pstmt.close();
            conn.close();
        } catch (SQLException se) {
            // 处理 JDBC 错误
            se.printStackTrace();
        } catch (Exception e) {
            // 处理 Class.forName 错误
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (pstmt != null) pstmt.close();
            } catch (SQLException se2) {
            }// 什么都不做
            try {
                if (conn != null)
                    conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
        System.out.println("Goodbye!");
    }
}

请添加图片描述
3. 向数据表添加日期;

添加日期数据时获取到的是String类型
1.String转化为java.util.Date
2.java.util.Date转化为java.sql.Date

// 1.String转化为java.util.Date
java.util.Date usdate = null;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
try {
      usdate = sdf.parse(sdate);
   } catch (ParseException e) {
       e.printStackTrace();
     }
//2.java.util.Date转化为java.sql.Date
long time = usdate.getTime();   //获取自1970年到现在的毫秒数

//这个日期就是java.sql.Date格式
java.sql.Date lsdate = new java.sql.Date(time);   

package com.five.jdbc.example;

import com.five.jdbc.common.DbUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 13:06
 */
public class InsertExample{
    public static void main(String[] args) throws SQLException {
        Scanner in = new Scanner(System.in);
        System.out.println("请输入学生编号:");
        int id = in.nextInt();
        System.out.println("请输入学生姓名:");
        String name = in.next();
        System.out.println("请输入学生班级:");
        String cname = in.next();
        System.out.println("请输入日期:");
        String sdate = in.next();

        Connection conn = null;
        PreparedStatement pstmt = null;
        // 1.String转化为java.util.Date
        java.util.Date usdate = null;
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            usdate = sdf.parse(sdate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //2.java.util.Date转化为java.sql.Date
        long time = usdate.getTime();   //获取自1970年到现在的毫秒数
        java.sql.Date lsdate = new java.sql.Date(time);   //这个日期就是java.sql.Date格式
        try {
            conn = DbUtils.getConnection();
            String sql = "insert into student(id,name,classname, sdate) values(?,?,?,?)";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);
            pstmt.setString(2, name);
            pstmt.setString(3, cname);
            pstmt.setDate(4, lsdate);
            int cnt  = pstmt.executeUpdate();   //写操作影响的行数
            System.out.println("cnt" + cnt);
            System.out.println(name = "添加成功啦!");
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }finally {
            DbUtils.closeConnection(null, pstmt, conn);
        }
    }
}

请添加图片描述
请添加图片描述

JDBC批处理

pstmt = conn.prepareStatement(sql);
pstmt.addBatch();  //将参数添加到批处理任务里面
pstmt.executeBatch();  //执行批处理任务

请添加图片描述
请添加图片描述
请添加图片描述

数据库连接池

数据库每次执行操作都会连接一次数据库,实际使用过程中频繁的连接务必会降低效率,数据库连接池可以在初始的时候进行数据库连接,需要时直接使用。

相关文档参见:参考文章

Druid连接池
  1. 官方地址 : 官方地址

请添加图片描述
2. 项目引入jar包,新建配置文件;
请添加图片描述
配置文件代码:

driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/study?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username=root
password=123456
  • 1.导入jar包 druid-1.0.9.jar
  • 2.定义配置文件:properties形式的
  • 3.加载配置文件。Properties
  • 4.获取数据库连接池对象:通过工厂来来获取 DruidDataSourceFactory
  • 5.获取连接:getConnection
  1. 示例代码;
package com.five.jdbc.example;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.five.jdbc.common.DbUtils;

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

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 18:01
 */
public class DruidExample {
    public static void main(String[] args) throws Exception {
        //1.加载属性文件
        Properties properties = new Properties();
        String propertyFile = DruidExample.class.getResource("/druid-config.properties").getPath();
        try {
            propertyFile = URLDecoder.decode(propertyFile, "UTF-8");
            properties.load(new FileInputStream(propertyFile));
        } catch (Exception e) {
            e.printStackTrace();
        }

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

        try {
            //2.获取DataSource数据源对象
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

            //3.创建数据库连接
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement("select * from student limit 0,20");
            rs = pstmt.executeQuery();
            //  展开结果集数据库
            while (rs.next()) {
                // 通过字段检索
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String classname = rs.getString("classname");
                //JDBC获取日期的时候使用java.sql.Date,继承于java.util.Date
                Date sdate = rs.getDate("sdate");
                // 输出数据
                System.out.print("ID: " + id);
                System.out.print(", 姓名: " + name);
                System.out.print(", 班级: " + classname);
                System.out.print(", 日期: " + sdate);
                System.out.print("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DbUtils.closeConnection(rs,pstmt,conn);
        }

    }
}

请添加图片描述

C3P0连接池
  1. 官方地址 : 官方地址

请添加图片描述

  1. 项目引入jar包,新建配置文件;
    请添加图片描述

配置文件代码:

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <!-- 使用默认的配置读取连接池对象 -->
    <default-config>
        <!--  连接参数 -->
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/study?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">123456</property>

        <!-- 连接池参数 -->
        <!--初始化的申请的连接数量-->
        <property name="initialPoolSize">10</property>
        <!--最大的连接数量-->
        <property name="maxPoolSize">20</property>
        <!--连接超时时间-->
        <property name="checkoutTimeout">3000</property>
    </default-config>
</c3p0-config>
  1. 示例代码;
package com.five.jdbc.example;

import javax.sql.DataSource;

import com.five.jdbc.common.DbUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.sql.*;

/**
 * Description:
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 21:46
 */
public class C3P0Example {
    public static void main(String[] args) throws SQLException {
        //1.加载配置文件
        //2.创建DataSource
        DataSource dataSource = new ComboPooledDataSource();
        //3.得到数据库连接
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            conn = dataSource.getConnection();
            pstmt = conn.prepareStatement("select * from student limit 0,20");
            rs = pstmt.executeQuery();
            // 展开结果集数据库
            while (rs.next()) {
                // 通过字段检索
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String classname = rs.getString("classname");
                //JDBC获取日期的时候使用java.sql.Date,继承于java.util.Date
                Date sdate = rs.getDate("sdate");
                // 输出数据
                System.out.print("ID: " + id);
                System.out.print(", 姓名: " + name);
                System.out.print(", 班级: " + classname);
                System.out.print(", 日期: " + sdate);
                System.out.print("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DbUtils.closeConnection(rs,pstmt,conn);
        }
    }
}

请添加图片描述

Commons DBUtils使用

Commons DBUtils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化JDBC编码的工作量,同时也不会影响程序的性能。

  1. 官方地址 : 官方地址
    请添加图片描述

  2. 项目引入jar包;
    请添加图片描述

  3. 示例代码,使用时需要仔细看文档,因为操作简单导致内容略显复杂;

package com.five.jdbc.example;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.five.jdbc.common.DbUtils;
import com.five.jdbc.entity.Student;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import javax.sql.DataSource;
import java.io.FileInputStream;
import java.net.URLDecoder;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.Properties;

/**
 * Description:    DbUtils联合Druid演示
 *
 * @Author: kk(专业bug开发)
 * DateTime: 2022-01-08 22:13
 */
public class DbUtilsExample {
    private static void query(){
        Properties properties = new Properties();
        String propertyFile = DbUtilsExample.class.getResource("/druid-config.properties").getPath();
        try {
            propertyFile = URLDecoder.decode(propertyFile, "UTF-8");
            properties.load(new FileInputStream(propertyFile));
            //2.获取DataSource数据源对象
            DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
            //关键语句,执行数据库操作
            QueryRunner qr = new QueryRunner(dataSource);
            List<Student> list = qr.query("select * from student limit ?,10", new BeanListHandler<>(Student.class),new Object[]{1});
            for (Student stu : list){
                System.out.print("ID: " + stu.getId());
                System.out.print(", 姓名: " + stu.getName());
                System.out.print(", 班级: " + stu.getCname());
                System.out.print(", 日期: " + stu.getSdate());
                System.out.print("\n");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        query();
    }
}

这部分内容我们一起学习了基础的JDBC到JDBC的开源工具,包括如何防止SQL注入、如何使用数据库连接池,所有的示例代码都是经过有效性验证的,一方面供给自己复习,另一方面供给一样在学习的小伙伴参考,如有错误欢迎指正~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK