0


超详细的JDBC基础,内含 C3P0 和 Druid 等 工具类 JAR 包下载

JDBC API 是一系列的接口,统一和规范了应用程序与数据库链接,执行sql语句,并得到返回结果等。在java.sql 和 javax.sql 中

1. JDBC概述和原理

** 1. 概述**

** (1)JDBC为Java程序操作不同的数据库提供了统一的接口,避免了细节.**

** (2)JDBC可以链接任何提供了JDBC的驱动程序的数据库系统,从而完成对数据库的任何操作.**

** 2. 原理示意图**

2. JDBC快速入门

   ** 1. JDBC程序有四个步骤**

** (1) 加载驱动 -- 加载Driver 类**

** (2) 获取连接 -- connection**

** (3)写sql语句 -- CRUD**

** (4) 释放资源-- close**

** 2. 第一个JDBC程序**

先在数据库 db_02 中,建一个actor表

create table Person (idt primary key inauto_increment,name varchar(32),sex varchar(1),phone varchar(12));

** (1)在加载驱动之前,先要导入 jar 包,其中含有 MySQL厂商 实现java提供接口的规范的类.**

         **   1. 下载jar包,前往 mysql官网**

** 2. 在java项目下建一个目录 把 jar 文件复制到该目录中**

** **

** 3. 导入项目 右键jar 选择 add...**

    ![](https://img-blog.csdnimg.cn/2fc8b39b874c4f9a9834913af735436c.png) 

** 1. 加载驱动**

** 2. 获得连接**

** 3. 写sql语句**

** 4. 释放资源**

三. 数据库连接的五种方式

  **  1. 就是通过 Driver ,不过是静态加载,依赖性很强**
   //加载驱动
        Driver driver = new Driver();

        // 2. 获得连接
        // jdbc:mysql:// 固定,是协议
        // localhost:3306/ IP 地址 和 端口号
        // db_02 数据库
        String url = "jdbc:mysql://localhost:3306/db_02";

        // 把用户和密码 封装到集合 properties 中

        Properties properties = new Properties();
        properties.setProperty("user", "root");
        properties.setProperty("password","liubo321");

        //获得连接
        Connection connect = driver.connect(url, properties);

        // 3. 编写sql语句 (1) 首先写sql语句(2)获得statement对象写入
        String sql = "insert actor values(null , '蔡徐坤', '男', '146843489')";
        Statement statement = connect.createStatement();
        int i = statement.executeUpdate(sql);  // 该对象可以写静态sql语句,并返回结果的行数 大于 0 即为成功

        System.out.println(i > 0 ? "成功" : "失败");

        //4. 释放资源
        connect.close();
        statement.close();

2. 通过反射,动态加载 Driver,依赖性降低

 public void connect02 () throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
        Driver driver = (Driver) aClass.newInstance();
        
    }

3. 使用 DriverManager 统一管理

**4. 利用反射机制,自动注册驱动 **

 public static void connect04 () throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");

        String url = "jdbc:mysql://localhost:3306/db_02";
        String user = "root";
        String password = "liubo321";

        Connection connection = DriverManager.getConnection(url, user, password);
        System.out.println(connection);
    }

5. 通过配置文件,更加灵活读取

 public static void connect05 () throws IOException, ClassNotFoundException, SQLException {
        Properties properties = new Properties();
        properties.load(new FileInputStream("src//mysql.properties"));

        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String driver = properties.getProperty("driver");
        String url = properties.getProperty("url");

        Class.forName(driver);

        Connection connection = DriverManager.getConnection(url,user,password);
        System.out.println(connection);
    }

配置文件 mysql.properties

四、ResultSet

** 1. 概述**

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

        Class.forName(driver);

        Connection connection = DriverManager.getConnection(url, user, password);

        Statement statement = connection.createStatement();
        String sql = "select * from actor";
        ResultSet resultSet = statement.executeQuery(sql);
        
        while (resultSet.next()) {
            int id = resultSet.getInt(1);//获取第一行信息
            String name = resultSet.getString(2);//获取第二行信息
            String sex = resultSet.getString(3);//获取第三行信息
            String phone = resultSet.getString(4);//获取第四行信息

            System.out.println(id + "\t" + name + "\t" + sex + "\t" + phone);
        }

        connection.close();
        statement.close();

    }

五、SQL注入

** 一、Statement 存在的危险**

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

** 2. 在建立连接之后,需要对数据库进行访问,执行命名或是sql语句,可以通过 **

            Statement [存在SQL注入问题]

            **PreparedStatement【预处理】**

** CallableStatement 【存储过程】**

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

二、使用 PreparedStatement 解决

** 1. 免去拼接字符串**

** 2. 有效解决SQL注入问题**

** 3.减少编译次数,提高效率**

使用 PreparenStatement 对象 ,

select * from emp where ename = ?and id = ?;

** 1. ? 代表占位符,可以使用 PreparenStatement 对象 提供一系列的setXXX ()方法,第一个参数代表第几个问号 从1开始**

2. executeQuery 返回结果集

3. executeUpdate (增,删,该)语句,返回 int 值,代表受影响的行数,大于0 成功

** 案例:使用PerparenStatement 完成对 表 actor 查询**

public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        // 加载驱动    
        
        String driver1 = properties.getProperty("driver");
        Class.forName(driver1);
        // 2. 连接,向配置文件读取信息
     
        properties.load(new FileInputStream("src//mysql.properties"));

        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
     
        String url = properties.getProperty("url");

        // 创建连接
       
        Connection connection = DriverManager.getConnection(url, user, password);
        String sql = "select * from actor where id = ?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,2);//查询ID为2的信息

        ResultSet resultSet = preparedStatement.executeQuery();

        System.out.println(resultSet.next() ? "成功" : "失败");
    }

六、JDBC API梳理

1. DriverManager

    1. getConnection(url,user,password) 获得链接

2.Statement 接口(存在SQL注入问题)

    1. executeUpdate(sql)执行dml语句

    2.executeQuery(sql) 执行select语句,返回结果集

    3. execute (sql) 执行任意语句,返回boolean值

** 3. PreparedStatement 接口(预处理)**

   1. executeUpdate(sql)执行dml语句

    2.executeQuery(sql) 执行select语句,返回结果集

    3. execute (sql) 执行任意语句,返回boolean值

    4.setXXX(占位符索引,赋予占位符的值),解决SQL注入

    5. setObject(占位符索引,赋予占位符的值)

4. ResultSet(结果集)

    1. next()向下移动,同时没有行返回false

    2. previous() 向上移动,如果没有上一行返回false

    3.getXXX(列的索引 | | 列的名称),获得对应列的值,接受类型是XXX

    4.getObject (列的索引 | | 列的名称)获得对应列的值,接受类型是Object

七、事务

** 1. jdbc 事务概述**

·基本介绍
1.JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
2.JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务
3.调用Connection 的 setAutoCommit(false) 可以取消自动提交事务
4.在所有的SQL语句都成功执行后,调用commitO;方法提交事务
5.在其中某个操作失败或出现异常时,调用rollback0;方法回滚事务

** 2.批处理 **

    简述
     1.当需要成批插入或者更新记录时。可以采用Java的批量更新机制,这一机制允许多条语句   一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。                
     2.JDBC的批量处理语句包括下面方法:
 **addBatch(O:添加需要批量处理的SQL语句或参数
 executeBatch():执行批量处理语句;
 clearBatch():清空批处理包的语句**
     3.JDBC连接MySQL时,如果要使用批处理功能,请再url中加参

数 ?rewriteBatchedStatements=true
4.批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减
少运行次数,效率大大提高

八、数据库连接池 内含 C3P0 and Druid 下载地址

** 1. 传统链接弊端 **

** 1. 对于每次建立一次链接,就要从Connection 对象 ,验证IP,密码等**

** 2. 不能控制连接数量,如果数量过多会导致MySQL奔溃**

** 3. 对于每一次连接,都要关闭,如果程序出现问题,会导致内存泄漏,导致重启MySQL**

** 2. 数据库连接池基本原理**

** 3. 连接池的种类**

数据库连接池种类
1.JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource 只是一个接口,该接口通常由第三方提供实现
2.C3P0 数据库连接池,速度相对较慢,稳定性不错(hibernate,spring)
3.DBCP数据库连接池,速度相对c3p0较快,但不稳定
4.Proxool数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
5.BoneCP数据库连接池,速度快
6.Druid(德鲁伊)是阿里提供的数据库连接池,集DBCP、C3PO、Proxool
优点于一身的数据库连接池

4. C3P0 连接方式

  **  1.  导入jar包 下载官网 C3P0 jar包下载地址**

 @Test
    //C3P0 第一种连接方式 ,用户密码,driver url 在程序中方设定
    public void C3p01 () throws IOException, PropertyVetoException, SQLException {

        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        Properties properties = new Properties();
        properties.load(new FileInputStream("src//mysql.properties"));
        String user = properties.getProperty("user");
        String password = properties.getProperty("password");
        String url = properties.getProperty("url");
        String driver = properties.getProperty("driver");

        // 2 配置连接数据库的信息
        comboPooledDataSource.setJdbcUrl(url);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setDriverClass(driver);

        // 初始化
        comboPooledDataSource.setInitialPoolSize(10);//初始化连接数
        comboPooledDataSource.setMaxPoolSize(50);//设置最大连接数
        // 3  获得链接

        Connection connection = comboPooledDataSource.getConnection();

        System.out.println("连接成功");
        connection.close();

2. 通过配置文件 来完成对数据库连接所需的信息

** 1. 在src目录下 建 c3p0-config.xml 文件**,其内容如下

<c3p0-config>
    <!--使用默认的配置读取数据库连接池对象 -->
        <named-config name="小鲨鱼">
            <!--加载驱动的Driver路径-->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
<!--指定连接数据库-->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db_02</property>
<!--连接数据库的用户-->
        <property name="user">root</property>
<!--对应的密码-->
        <property name="password">123456</property>

        <!-- 连接池参数 -->
        <!--初始化申请的连接数量-->
        <property name="initialPoolSize">5</property>
<!--每次增长链接的数-->
        <property name="acquireIncrement">5</property>
        <!--最大的连接数量-->
        <property name="maxPoolSize">10</property>
    <!--最小连接数-->
        <property name="minPoolSize">5</property>
        <!--超时时间-->
        <property name="checkoutTimeout">3000</property>
<!--每个连接对象可连接的最多的命令对象数-->
        <property name="maxStatementsPerConnection">2</property>
       </named-config>
</c3p0-config>
  **          2. 通过程序向连接池中取出连接**
 public void C3P02 () throws SQLException {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource("小鲨鱼");
        Connection connection = comboPooledDataSource.getConnection();
        System.out.println("通过配置文件连接");
    }

5. 德鲁伊连接池 德鲁伊JAR包下载地址

** 步骤**

** 1. 从官方下载 druid jar 包,导入项目中 **

** 2. 在src下面加入 druid 的配置文件**

** 3. 加载驱动,使用 ** DruidDataSourceFactory.createDataSource(properties);

** 4. 获得连接**

** 1. 案例:对MySQL数据库完成连接使用Druid连接池**

public class Druid_ {
    @Test
    public void  Druid_connection_pool() throws Exception {
        // 创建properties对象,加载信息

        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\Druid-config.properties"));

        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        dataSource.getConnection();

        System.out.println("连接成功");

    }

** 2. 配置 Druid-config.perproties 配置文件如下 导入 src 目录下**

#key=vlaue
driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/db_02?rewriteBatchedStatements=true

username=root

password=liubo321

initialSize=10

maxActive=50

maxWait=5000

六、Apche-DButils

   **        简述**

** 由于,上述方法,Connection 释放资源时,返回的ResultSet就不能使用。要对ResultSet数据可以想使用的时候就使用,我们要把这个结果集,封装到ArraryList<类>中,该类的属性与表中字段相等,该类称为JavaBean**

JavaBean 是为该类是表的映射

     代码实现 - Actor 类
package com.study.myDButils;

/**
 * +----+-----------+------+------+-----------+
 * | id int name varchar     | sex varchar  | sorc double | phone varchar    |
 * +----+-----------+------+------+-----------+
 * actor 表
 */
public class Actor {
    private Integer id;
    private String name;
    private String sex;
    public Double sorc;
    public String phone;

    public Actor() {//必须提供无参构造器

    }

    public Actor(Integer id, String name, String sex, Double sorc, String phone) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.sorc = sorc;
        this.phone = phone;
    }

    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 getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Double getSorc() {
        return sorc;
    }

    public void setSorc(Double sorc) {
        this.sorc = sorc;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Actor{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", sorc=" + sorc +
                ", phone='" + phone + '\'' +
                '}';
    }
}

** 结果集保存**

 @Test
    public void MyDButils01() throws SQLException {
        ArrayList<Actor> actors = new ArrayList<>();//JavaBean 把结果集保存在ArrayList中
        Connection connection = JdbcDruid.getConnection();//获得连接

        String sql = "select * from actor where id = ?";

        PreparedStatement preparedStatement = connection.prepareStatement(sql);//获取preparedStatement执行sql语句

        preparedStatement.setInt(1,1);

        ResultSet resultSet = preparedStatement.executeQuery();

        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String name = resultSet.getString("name");
            String sex = resultSet.getString("sex");
            double sorc = resultSet.getDouble("sorc");
            String phone = resultSet.getString("phone");
            actors.add(new Actor(id,name,sex,sorc,phone));
        }

        JdbcDruid.close(preparedStatement,connection,resultSet);

        System.out.println(actors);
    }

对上述方法进行优化 - 引出 Apche-DButils

** 1. 对 **Apche-DButils 介绍 下载JAR包

·基本介绍

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

· DbUtils类
1.QueryRunner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查、批处理
2.使用QueryRunner类实现查询
3.ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形
式,
Q
1.ArrayHandler:把结果集中的第一行数据转成对象数组。
2. ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
3. BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
4. BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
5. ColumnListHandler:将结果集中某一列的数据存放到List中。
6. KeyedHandler(name):将结果集中的每行数据都封装到Map里,再把这些map再存到一个map里,其key为指定的key。
7. MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
8. MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List

    9. ScalarHandler 返回一个字段一列信息
  **  2. 案列:使用 DbUtils 完成对actor表的查询,并把结果集加到list中**
package com.study.myDButils;

import com.study.F_jdbc.untils.JdbcDruid;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.jupiter.api.Test;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * 使用DbUtils 完成对actor表的查询,并把结果集加到list中
 */
public class DButils {
    @Test
    public void DButlis01() throws SQLException {
        Connection connection = JdbcDruid.getConnection();
        
        String sql = "select * from actor where id >= ?";

        QueryRunner queryRunner = new QueryRunner();
        /**
         * connection 放入一个链接
         * sql 写入sql语句
         * new BeanListHandler<>(Actor.class)
         * 通过反射 获得Actor的属性,并把结果集存在List中
         * 最后为可变参数,是 给 ? 占位符 赋值
         */
        List<Actor> query = queryRunner.query(connection, sql, new BeanListHandler<>(Actor.class), 1);
        
        for(Actor a :query) {
            System.out.println(a);
        }
        //queryRunner.query 会自动吧statement 关闭,和 resultSet
        JdbcDruid.close(null,connection,null);
    }
}

** QueryRunner对象中.update 方法,执行失sql语句的DML语句、**

    public void DButils_DML() throws SQLException {
        Connection connection = JdbcDruid.getConnection();

        String sql = "delete from actor where id = ?";

        // int 返回的是sql语句影响表中的行数
        int update = new QueryRunner().update(connection, sql, 1);

        System.out.println(update > 0 ? "删除成功" : "没有影响到表");
    }
}

十、BasicDAO

DAO - - - Data Access Object 【数据访问对象】

概述上述代码缺点

    1. SQL 语句写死,不能通过参数传递,通用性不好.

    2. 对于 select 语句 返回结果集,返回类型不确定.

** 2. 编写BasicDAO**

** 1. 建四个包,分别存入不同的类**

** 1. com.study.dao_**

** 2. com.study.dao_.JavaBean // 存放 与表中数据映射的类**

** 3. com.study.dao_.utils // 存放工具类**

** 4. com.study.dao_.dao //存放 XXxDAO**

** 5.com.study.dao_.text // 测试类**

** 1. com.study.dao_.dao **

package com.study.dao_.dao;

import com.study.dao_.utils.JDBCUtilsByDruid;
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 java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * 完成其他DAO对象使用的方法
 */
public class BasicDao<T> {
    private QueryRunner qr = new QueryRunner();

    private Connection connection = null;
    //执行dml语句
    public int queryDate (String sql,Object...parameters) {
        int updates;

        try {
            this.connection = JDBCUtilsByDruid.getConnection();
          updates =  qr.update(connection,sql,parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null,connection,null);
        }
        return updates;
    }

    //查询多行结果集

    public List<T> queryMulti (String sql, Class<T> aclass,Object... parameters) {
        try {
            this.connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection, sql, new BeanListHandler<>(aclass), parameters);

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null,connection,null);
        }

    }

    //查询单行数据
    public T querySingle (String sql, Class<T> aclass, Object...parameters) {
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return qr.query(connection,sql,new BeanHandler<>(aclass),parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null,connection,null);
        }
    }

    //查询单行单列数据
    public Object queryScalar (String sql, Object...parameters) {
        try {
            connection = JDBCUtilsByDruid.getConnection();
            return  qr.query(connection,sql,new ScalarHandler<>(),parameters);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtilsByDruid.close(null,connection,null);
        }
    }

}

** 2. com.study.dao_.domain**

package com.study.dao_.domain;

/**
 * +----+-----------+------+------+-----------+
 * | id int name varchar     | sex varchar  | sorc double | phone varchar    |
 * +----+-----------+------+------+-----------+
 * actor 表
 */
public class Actor {
    private Integer id;
    private String name;
    private String sex;
    public Double sorc;
    public String phone;

    public Actor() {//必须提供无参构造器

    }

    public Actor(Integer id, String name, String sex, Double sorc, String phone) {
        this.id = id;
        this.name = name;
        this.sex = sex;
        this.sorc = sorc;
        this.phone = phone;
    }

    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 getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Double getSorc() {
        return sorc;
    }

    public void setSorc(Double sorc) {
        this.sorc = sorc;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "Actor{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", sorc=" + sorc +
                ", phone='" + phone + '\'' +
                '}';
    }
}
  1. com.study.dao_.tex
package com.study.dao_.text;

import com.study.dao_.dao.ActorDao;
import com.study.dao_.domain.Actor;
import org.junit.jupiter.api.Test;

import java.util.List;

public class TextDao {
    @Test
  public void text01() {
        ActorDao actorDao = new ActorDao();
        String sql = "select * from actor where id > ?";
        List<Actor> list = actorDao.queryMulti(sql, Actor.class,2);

        for(Actor actor : list) {
            System.out.println(actor);
        }

        //单行记录
        String sql1 = "select * from actor where id = ?";
      Object o = actorDao.querySingle(sql, Actor.class, 3);
        System.out.println("单行记录");
      System.out.println(o);

      //单行单列信息
    String sql3 = "select name from actor where id = ?";
        Object o1 = actorDao.queryScalar(sql3, 3);
        System.out.println("单列数据");
        System.out.println(o1);
    }

}

本文转载自: https://blog.csdn.net/jmgufss/article/details/126658826
版权归原作者 一直在进步的派大星 所有, 如有侵权,请联系我们删除。

“超详细的JDBC基础,内含 C3P0 和 Druid 等 工具类 JAR 包下载”的评论:

还没有评论