JDBC与数据库连接池学习笔记

JDBC原理图
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
导入jar包
JDBC与数据库连接池学习笔记
连接方式1
JDBC与数据库连接池学习笔记
连接方式2 反射获取Driver
JDBC与数据库连接池学习笔记
方法3
JDBC与数据库连接池学习笔记

方法4 Class.forname自动完成驱动注册(这种方式推荐)
JDBC与数据库连接池学习笔记
driver底层有静态代码块在类加载的时候自动完成驱动注册
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
但是建议写上,更加明确

方法5
在方式4的基础上,使用配置文件,使连接更加灵活(推荐使用)
JDBC与数据库连接池学习笔记
配置文件内容
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

结果集resultSet
简单理解为执行select返回的表
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

Statement
Statement对象,用于执行静态sql语句并返回其生成结果的对象
连接建立后需要对数据库进行访问,执行命名或sql语句,可以通过
Statement[存在sql注入]
PreparedStatement [预处理] (主要用这个开发应用)
CallableStatement[存储过程]
SQL注入
利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的sql语句段或命令,恶意攻击数据库
JDBC与数据库连接池学习笔记

预处理查询
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
预处理dml
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
封装JDBCUtils工具类
JDBC与数据库连接池学习笔记

public class JDBCUtils {
    private static String user;
    private static String password;
    private static String url;
    private static String driver;

    static{
        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("src\\mysql.properties"));
            user = properties.getProperty("user");
            password = properties.getProperty("password");
            url = properties.getProperty("url");
            driver = properties.getProperty("driver");
        } catch (IOException e) {
            //实际开发中可以这样处理
            //1,将编译异常转为运行异常
            //2,这时调用者可以选择捕获异常,也可以选择默认处理该异常,比较方便
            throw new RuntimeException(e);
        }
    }
    //连接函数
    public static Connection getconnection(){
        try {
            return DriverManager.getConnection(url,user,password);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    //关闭函数
    public static void close(ResultSet set, Connection connection, Statement statement){
        try {
            if(set != null){
                set.close();
            }

            if(statement != null){
                statement.close();
            }
            if(connection!=null){
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

测试

public class JDBCUtils_use {
    public static void main(String []args)  {
        Connection connection = null;
        //编写sql语句
        String sql = "insert into admin values(?,?)";
        PreparedStatement preparedStatement = null;

        try {
            //使用工具类获取连接
            connection = JDBCUtils.getconnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1,"Bob");
            preparedStatement.setString(2,"123456");
            int rows = preparedStatement.executeUpdate();
            if(rows != 0){
                System.out.println("插入成功~");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //使用工具类关闭连接
            JDBCUtils.close(null,connection,preparedStatement);
        }
    }
}

执行成功,数据成功插入到数据库中

事务
JDBC与数据库连接池学习笔记
例如用事务解决转账问题

connection.setAutoCommit(false);
connection.rollback();
connection.commit();

批处理
传统方法插入数据
JDBC与数据库连接池学习笔记

JDBC与数据库连接池学习笔记
批处理插入数据
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
addbatch()底层
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

数据库连接池

传统方式获取释放连接存在问题
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
数据库连接池
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
数据库连接池的种类
JDBC的数据库连接池通常使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方实现
(1)C3P0 数据库连接池(hibernate,spring)
相对较慢,稳定性不错
(2)DBCP 数据库连接池
相对c3p0较快,不稳定
(3)Proxool数据库连接池
有监控连接池状态的功能,稳定性较c3p0差一点
(4)BoneCP
速度快
(5)Druid 阿里提供的数据库连接池
集DBCP,C3P0,Proxool优点于一身

C2P0数据库连接池方式一
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
方式二 使用配置文件来完成
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

JDBC与数据库连接池学习笔记

		long STATT = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            Connection connection = comboPooledDataSource.getConnection();
            //System.out.println("连接成功~~");
            connection.close();
        }
        long END = System.currentTimeMillis();
         System.out.println("C3P0的5000耗时 "+(END-STATT));

JDBC与数据库连接池学习笔记

Druid连接池(德鲁伊)
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

Properties properties = new Properties();
        properties.load(new FileInputStream("src\\druid.properties"));
        //使用配置文件获得连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
        System.out.println("开始测试~");
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5000; i++) {
            Connection connection = dataSource.getConnection();
//            System.out.println("获取连接成功~");
            connection.close();
        }
        long end = System.currentTimeMillis();
        System.out.println("druid 5000次耗费时间 "+(end-start));

JDBC与数据库连接池学习笔记
发现5000次连接并不能体现出Druid的优势,反而比C3P0更慢
于是将连接数扩展到500000次

long STATT = System.currentTimeMillis();
        for (int i = 0; i < 500000; i++) {
            Connection connection = comboPooledDataSource.getConnection();
//            System.out.println("连接成功~~");
            connection.close();
        }
        long END = System.currentTimeMillis();
        System.out.println("C3P0的500000次连接耗时 "+(END-STATT));

JDBC与数据库连接池学习笔记

		long start = System.currentTimeMillis();
        for (int i = 0; i < 500000; i++) {
            Connection connection = dataSource.getConnection();
//            System.out.println("获取连接成功~");
            connection.close();
        }
        long end = System.currentTimeMillis();
        System.out.println("druid 500000次耗费时间 "+(end-start));

JDBC与数据库连接池学习笔记

此时体现出druid的性能,实际开发推荐使用Druid
jdbcutilsbydruid:

public class JDBCUtilsbyDruid {
    private static DataSource dataSource;

    static{
        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("src\\druid.properties"));
            dataSource = DruidDataSourceFactory.createDataSource(properties);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //编写连接函数
    public static Connection getconnection() throws SQLException {
        return dataSource.getConnection();
    }
    //编写关闭函数
    public static void close(ResultSet resultSet, Statement statement,Connection connection){
        try {
            if(resultSet != null){
                resultSet.close();
            }
            if(statement != null){
                statement.close();
            }
            if(connection != null){
                //此处的连接关闭并没有实际关闭与数据库的连接,仅仅是将连接池的引用断开
                connection.close();
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

这里的close方法与前面JDBCutils中的close是不同的,此处的close方法断开的是Druid实现的connection,并不是真正的与数据库连接的connnection,二者本质上实现类不同,Connection只是个接口
(运行类型不同)

ApDBUtils
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
通过将数据库内返回的结果集数据封装到list,可以在连接关闭后复用数据

Apache-DBUtils
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

public void testDbutils() throws SQLException {
        //测试DButils,使用Druid连接池
        //1.获取连接
        Connection connection = JDBCUtilsbyDruid.getconnection();
        //2.引入DButils相关的jar包
        //3.创建QueryRunner
        QueryRunner queryRunner = new QueryRunner();
        //4.执行相关的方法,返回Arraylist结果集
        String sql = "select * from account";
        /**
         * 老韩解读
         * (1)query方法就是执行sql语句,返回Resultset结果集,封装到Arraylist中
         * (2)返回集合
         * (3)Connection :连接
         * (4)sql:要执行的sql语句
         * (5)new BeanListHandler<>(account.class)   在将Resultset取出后->account对象->封装到Arraylist
         * 过程中底层需要通过反射查看account类里有哪些属性,然后进行封装
         * (6) 1 就是给sql语句中的?赋值的,是一个可变参数的
         * (7)底层得到的resultset会在 query关闭,且PreparedStatement也会关闭
         */
        List<account> list = queryRunner.query(connection, sql, new BeanListHandler<>(account.class));
        System.out.println("输出集合信息");
        for(account ac : list){
            System.out.println(ac);
        }
        //释放资源
        JDBCUtilsbyDruid.close(null,null,connection);
    }
输出集合信息

account{id=1, name='马云', balance=2800.0}

account{id=2, name='马化腾', balance=10100.0}

查询单行数据使用的handler
JDBC与数据库连接池学习笔记
查询结果是单行单列,返回Object.使用的handler
JDBC与数据库连接池学习笔记
dbutils + druid 执行 dml语句

@Test
    public void testDML() throws SQLException {
        //测试DButils,使用Druid连接池
        //1.获取连接
        Connection connection = JDBCUtilsbyDruid.getconnection();
        //2.引入DButils相关的jar包
        //3.创建QueryRunner
        QueryRunner queryRunner = new QueryRunner();
        String sql = "UPDATE account set name ='王健林'where id = 1" ;
        //返回值为执行后受影响的行数
        int Affectedrows = queryRunner.update(connection, sql);
        if(Affectedrows>0){
            System.out.println("更新成功");
        }
        JDBCUtilsbyDruid.close(null,null,connection);
    }

JDBC与数据库连接池学习笔记

public void testDML() throws SQLException {
        //测试DButils,使用Druid连接池
        //1.获取连接
        Connection connection = JDBCUtilsbyDruid.getconnection();
        //2.引入DButils相关的jar包
        //3.创建QueryRunner
        QueryRunner queryRunner = new QueryRunner();
        String sql = "insert into account values(null,?,?)" ;
        //返回值为执行后受影响的行数
        int Affectedrows = queryRunner.update(connection, sql,"许家印",10000);
        if(Affectedrows>0){
            System.out.println("插入成功");
        }
        JDBCUtilsbyDruid.close(null,null,connection);
    }

JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
BasicDao
JDBC与数据库连接池学习笔记
Dao(Data access object)
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记
JDBC与数据库连接池学习笔记

上一篇:30. 协程、进程线程补充


下一篇:CodeQL 入门- 环境建置