JDBC进阶篇-ROM、主键回显、批量操作、连接池

实体类和ORM

  • 在使用JDBC操作数据库时,我们会发现数据都是零散的,明明在数据库中是一行完整的数据,到了Java中变成了一个一个的变量,不利于维护和管理。而我们Java是面向对象的,一个表对应的是一个类,一行数据就对应的是Java中的一个对象,一个列对应的是对象的属性,所以我们要把数据存储在一个载体里,这个载体就是实体类!
  • ORM(Object Relational Mapping)思想,对象到关系数据库的映射,作用是在编程中,把面向对象的概念跟数据库中表的概念对应起来,以面向对象的角度操作数据库中的数据,即一张表对应一个类,一行数据对应一个对象,一个列对应一个属性!
  • 当下JDBC中为手动ORM。自动ORM要学习ORM框架,比如MyBatis、JPA等。

ORM实现步骤

  • 封装实体类JavaBean
    • 类和数据库名对应,但是表名一般缩写,类名要全写
    • JavaBean中属性与数据库中列名相对应,数据库中列名用下划线分隔,属性名用驼峰
    • 实现无参构造器,有参构造器,get、set方法等
  • 使用JDBC连接数据库
		//1.注册驱动
//        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取数据库连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名", "root","密码");

        //3.创建PreparedStatement对象,并预编译SQL语句,使用?占位符
        PreparedStatement preparedStatement = connection.prepareStatement("select 查询字段 表名");

        //4.为占位符赋值,索引从1开始,执行SQL语句,获取结果
        //preparedStatement.setInt(第几个占位符, 数据字符串);,有?占位符时添加
        ResultSet resultSet = preparedStatement.executeQuery();
	      //预先创建实体类变量,自定义
        Employee employee = null; // 实体类 实体类名 = null;
          //预先创建类集合,自定义
        List<Employee> employeeList = new ArrayList<>();
        //5.封装
        while (resultSet.next()) {
            int 属性名1 = resultSet.getInt("列名");
            String 属性名2 = resultSet.getString("列名");
            Double 属性名3 = Double.valueOf(resultSet.getString("列名"));
            
          	//当结果集中有数据,再进行对象的创建
            employee = new Employee(属性名1,属性名2,属性名3);
            //将每次循环封装的一行数据的对象存储在集合里
            employeeList.add(employee);
        }
        
		//6.处理结果,遍历集合
		for(Employee emp : employeeList){
			System.out.println("employee = " + emp);
		}

        //7.释放资源(先开后关原则)
        resultSet.close();
        preparedStatement.close();
        connection.close();

    }

主键回显

在数据中,执行新增操作时,主键列为自动增长,可以在表中直观的看到,但是在Java程序中,我们执行完新增后,只能得到受影响行数,无法得知当前新增数据的主键值。在Java程序中获取数据库中插入新数据后的主键值,并赋值给Java对象,此操作为主键回显。

  • 在创建preparedStatement对象时,传入逐渐回显参数Statement.RETURN_GENERATED_KEYS,告诉对象我需要获取主键
  • 调用preparedStatement对象中getGeneratedKeys()方法,获取一行一列结果集
  • 在结果集中获取主键列值
		//创建preparedStatement对象,传入需要主键回显参数Statement.RETURN_GENERATED_KEYS
        PreparedStatement preparedStatement = connection.prepareStatement("insert into t_emp values  (?,?)",Statement.RETURN_GENERATED_KEYS);

		//获取生成的主键列值,返回的是resultSet,在结果集中获取主键列值
        ResultSet resultSet = preparedStatement.getGeneratedKeys();
        if (resultSet.next()){
        	//获取主键列值
            int empId = resultSet.getInt(1);
            employee.setEmpId(empId);
        }

批量操作

1、必须在连接数据库的URL后面追加?rewriteBatchedStatements=true,允许批量操作
2、新增SQL必须用values。且语句最后不要追加;结束
3、调用addBatch()方法,将SQL语句进行批量添加操作
4、统一执行批量操作,调用executeBatch()

//1.追加?rewriteBatchedStatements=true
Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu?rewriteBatchedStatements=true", "root", "atguigu");

//2.sql语句不要;,批量处理时转换为sql语句 insert into 表名 values(值1,值2,值3),values(值21,值22,值23)...
String sql = "insert into 表名 values (?,?,?)";

 for(int i = 0;i<10000;i++){
    //为占位符赋值
    preparedStatement.setString(1, "值1");
    preparedStatement.setDouble(2, "值2");
    preparedStatement.setInt(3, "值3");
	//3.调用addBatch()方法,将SQL语句进行批量添加操作,转为批量添加值的SQL语句
    preparedStatement.addBatch();
}

//4.执行批量操作
preparedStatement.executeBatch();

连接池

现有问题

  • 每次操作数据库都要获取新连接,使用完毕后就close释放,频繁的创建和销毁造成资源浪费。
  • 连接的数量无法把控,对服务器来说压力巨大。

连接池

  • 连接池就是数据库连接对象的缓冲区,通过配置,由连接池负责创建连接、管理连接、释放连接等操作。
  • 预先创建数据库连接放入连接池,用户在请求时,通过池直接获取连接,使用完毕后,将连接放回池中,避免了频繁的创建和销毁,同时解决了创建的效率。
  • 当池中无连接可用,且未达到上限时,连接池会新建连接。
  • 池中连接达到上限,用户请求会等待,可以设置超时时间。
  • 例子:排队买票时,我们不可能给每位顾客提供一个售票窗口(连接池),当顾客人数小于售票窗口时,顾客可以在空余售票窗口买票,当顾客人数大于售票窗口时,只能进行排队买票,当人员过多,排队时间过长时,售票窗口的售票人员告诉你,还需要排队XX时间,你如果有其余的事情要做,可以先完成其余事情
    • 售票窗口 = 连接池
    • 买票 = 连接
    • 购票完毕 = 释放连接
    • 顾客人数小于售票窗口 = 池中连接未达到上限
    • 顾客人数大于售票窗口 = 池中连接达到上限
    • 顾客排队 = 请求等待
    • 顾客排队时间 = 超时时间

常见连接池

JDBC 的数据库连接池使用 javax.sql.DataSource接口进行规范,所有的第三方连接池都实现此接口,自行添加具体实现!也就是说,所有连接池获取连接的和回收连接方法都一样,不同的只有性能和扩展功能!

  • DBCP 是Apache提供的数据库连接池,速度相对C3P0较快,但自身存在一些BUG。
  • C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。
  • Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能, 稳定性较c3p0差一点
  • Druid 是阿里提供的数据库连接池,是集DBCP 、C3P0 、Proxool 优点于一身的数据库连接池,性能、扩展性、易用性都更好,功能丰富(相当于精修房(扩展功能多),国内使用率较高)
  • Hikari(ひかり[shi ga li]) 取自日语,是光的意思,是SpringBoot2.x之后内置的一款连接池,基于 BoneCP (已经放弃维护,推荐该连接池)做了不少的改进和优化,口号是快速、简单、可靠。(相当于毛坯房(扩展功能少),追求极致速度)
  • 如果想要扩展性推荐使用Druid
  • 如果只是追求极致的效率使用Hikari

Druid连接池使用

硬编码方式(了解):将连接池的配置信息和Java代码耦合在一起。

        1、创建DruidDataSource连接池对象。
        2、设置连接池的配置信息【必须 | 非必须】
        3、通过连接池获取连接对象
        4、回收连接【不是释放连接,而是将连接归还给连接池,给其他线程进行复用】
		//1.创建DruidDataSource连接池对象。
        DruidDataSource druidDataSource = new DruidDataSource();

        //2.设置连接池的配置信息【必须 | 非必须】
        //2.1 必须设置的配置
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql:///数据库");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("密码");

        //2.2 非必须设置的配置
        druidDataSource.setInitialSize(10);//初始化10个连接,超过8个必须设置setMaxActive
        druidDataSource.setMaxActive(20);//最大连接20个,默认8个
        
        //3.通过连接池获取连接对象
        Connection connection = druidDataSource.getConnection();

        //基于connection进行CRUD

        //4.回收连接
        connection.close();

软编码方式(推荐)

在项目目录下创建resources文件夹,标识该文件夹为资源目录,创建db.properties配置文件,将连接信息定义在该文件中

# druid连接池需要的配置参数,key固定命名
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql:///数据库
username=root
password=密码
initialSize=10
maxActive=20

Java代码

		//1.创建Properties集合,用于存储外部配置文件的key和value值。
        Properties properties = new Properties();

        //2.读取外部配置文件,获取输入流,加载到Properties集合里。
        InputStream inputStream = DruidTest.class.getClassLoader().getResourceAsStream("db.properties");
        properties.load(inputStream);

        //3.基于Properties集合构建DruidDataSource连接池
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        //4.通过连接池获取连接对象
        Connection connection = dataSource.getConnection();

        //5.开发CRUD

        //6.回收连接
        connection.close();

HikariCP连接池使用

硬编码方式

1、创建HikariDataSource连接池对象
2、设置连接池的配置信息【必须 | 非必须】
3、通过连接池获取连接对象
4、回收连接

	//1.创建HikariDataSource连接池对象
    HikariDataSource hikariDataSource = new HikariDataSource();

    //2.设置连接池的配置信息【必须 | 非必须】
    //2.1必须设置的配置
    hikariDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
    hikariDataSource.setJdbcUrl("jdbc:mysql:///数据库");
    hikariDataSource.setUsername("root");
    hikariDataSource.setPassword("密码");

    //2.2 非必须设置的配置
    hikariDataSource.setMinimumIdle(10);//最小连接数量
    hikariDataSource.setMaximumPoolSize(20);//最大连接数量

    //3.通过连接池获取连接对象
    Connection connection = hikariDataSource.getConnection();

    //4.回收连接
    connection.close();

软编码方式

在项目下创建resources/hikari.properties配置文件

driverClassName=com.mysql.cj.jdbc.Driver
jdbcUrl=jdbc:mysql:///数据库
username=root
password=密码
minimumIdle=10
maximumPoolSize=20

Java代码

//1.创建Properties集合,用于存储外部配置文件的key和value值。
        Properties properties = new Properties();
        
        //2.读取外部配置文件,获取输入流,加载到Properties集合里。
        InputStream inputStream = HikariTest.class.getClassLoader().getResourceAsStream("db.properties");
        properties.load(inputStream);
        
        // 3.创建Hikari连接池配置对象,将Properties集合传进去
        HikariConfig hikariConfig = new HikariConfig(properties);
        
        // 4. 基于Hikari配置对象,构建连接池
        HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);

        // 5. 获取连接
        Connection connection = hikariDataSource.getConnection();
        System.out.println("connection = " + connection);
        
        //6.回收连接
        connection.close();
  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值