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

目录

1. JDBC概述和原理

2. JDBC快速入门

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

四、ResultSet

五、SQL注入

六、JDBC API梳理

七、事务

八、数据库连接池

C3P0 连接方式包含 JAR 下载地址

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

九、Apche-DButils

1. 对Apche-DButils 介绍 包含下载JAR包地址

十、BasicDAO


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…

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 " />

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 = " />

六、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 文件,其内容如下

                                com.mysql.jdbc.Driver        jdbc:mysql://localhost:3306/db_02        root        123456                        5        5                10            5                3000        2       

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=vlauedriverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/db_02" />

代码实现 - 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 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 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 {    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 queryMulti (String sql, Class 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 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 + '\'' +                '}';    }}

3.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 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);    }}