细致刨析JDBC ② 进阶篇

news2024/11/13 8:56:12

目录

一、JDBC拓展

1.实体类和ORM

Ⅰ、ORM思想封装单个对象

Ⅱ、ORM思想封装集合

2.主键回显

3.批量操作

① 循环逐条数据进行添加

② 批量进行添加

二、连接池

1.现有问题

2.连接池

3.常见连接池

4.Druid连接池使用

使用步骤:

硬编码

软编码

5.HikariCP连接池使用

使用步骤

硬编码

软编码


坚持别人无法坚持的坚持,才能拥有别人无法拥有的拥有

                                                                                —— 24.9.7

一、JDBC拓展

1.实体类和ORM

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

Ⅰ、ORM思想封装单个对象

将数据库中的数据R封装在Java中的对象O上,这个过程叫做映射M

package JDBC_Advance;

import JDBC_Advance.Pojo.Employee;
import org.junit.Test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class JDBCAdvanced {
    @Test
    public void testORM1() throws Exception{
        Connection con = DriverManager.getConnection("jdbc:mysql:///javawebjdbc","root","954926928lcl");
        PreparedStatement ps = con.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp where emp_id=?");
        ps.setInt(1,1);

        ResultSet rs = ps.executeQuery();

        // 创建一个employee对象
        Employee emp = null;

        if(rs.next()){
            emp = new Employee();
            int empId = rs.getInt("emp_id");
            String empName = rs.getString("emp_name");
            double empSalary = rs.getDouble("emp_salary");
            int empAge = rs.getInt("emp_age");

            // 为对象属性赋值,这就是个ORM的体现过程,将数据库R中的数据封装在Java中的Object对象上,这个过程叫做映射 M
            emp.setEmpId(empId);
            emp.setEmpName(empName);
            emp.setEmpSalary(empSalary);
            emp.setEmAge(empAge);
        }

        System.out.println(emp);

        rs.close();
        ps.close();
        con.close();
    }
}

Ⅱ、ORM思想封装集合

① 创建对象——>② 将每一次对象存储在集合中——>③ 遍历集合

    @Test
    public void testORMList() throws Exception{
        Connection con = DriverManager.getConnection("jdbc:mysql:///javawebjdbc","root","954926928lcl");
        PreparedStatement ps = con.prepareStatement("select emp_id,emp_name,emp_salary,emp_age from t_emp");
        ResultSet rs = ps.executeQuery();

        Employee emp = null;

        // 创建一个List泛型集合
        List<Employee> employeelist = new ArrayList<>();

        while(rs.next()) {
            emp = new Employee();

            int empId = rs.getInt("emp_id");
            String empName = rs.getString("emp_name");
            double empSalary = rs.getDouble("emp_salary");
            int empAge = rs.getInt("emp_age");

            emp.setEmpId(empId);
            emp.setEmpName(empName);
            emp.setEmpSalary(empSalary);
            emp.setEmAge(empAge);

            // 将每次循环创建的一行数据的对象存储在集合里
            employeelist.add(emp);
        }
        // 5.遍历集合,处理结果
        for (Employee employee : employeelist) {
            System.out.println(employee);
        }

        // 6.资源的释放
        rs.close();
        ps.close();
        con.close();
    }

2.主键回显

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

    @Test
    public void testReturnPK() throws Exception{
        // 1.获取链接
        Connection con = DriverManager.getConnection("jdbc:mysql:///javawebjdbc","root","954926928lcl");

        // 2.预编译SQL语句
        String sql = "insert into t_emp(emp_name,emp_salary,emp_age) values(?,?,?)";

        // 3.对数据库声明主键回显,添加元素:RETURN_GENERATED_KEYS,主键回显,告知数据库在修改数据库后返回新增数据的主键列
        PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

        // 4.创建对象,将对象的属性值,赋值在?占位符上(ORM思想)
        Employee emp = new Employee(null,"jack",123.45,28);
        ps.setString(1,emp.getEmpName());
        ps.setDouble(2,emp.getEmpSalary());
        ps.setInt(3,emp.getEmAge());

        // 5.执行SQL,并获取返回的结果
        int res = ps.executeUpdate();
        ResultSet rs2 = null;

        // 6.处理结果
        if(res > 0){
            System.out.println("成功");
            // 返回的主键值返回的是单行单列的结果,存储在rs2中获取当前新增数据的主键列,回显到Java中emp对象的empId属性上
            // 返回的主键值返回的是单行单列的结果,存储在rs2中
            rs2 = ps.getGeneratedKeys();
            if(rs2 .next()){
                int empId = rs2.getInt(1);
                emp.setEmpId(empId);
            }
            // 输出员工对象(查询所有数据)
            System.out.println(emp);
        }else{
            System.out.println("失败");
        }

        System.out.println(emp);

        // 7.释放资源
        if(rs2!=null){
            rs2.close();
            ps.close();
            con.close();
        }
    }

3.批量操作

① 循环逐条数据进行添加

    @Test
    public void testMoreInsert() throws Exception{
        // 1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        // 2.获取链接
        Connection con = DriverManager.getConnection("jdbc:mysql:///javawebjdbc","root","954926928lcl");

        // 3.编写sql语句
        String sql = "insert into t_emp(emp_name,emp_salary,emp_age) values(?,?,?)";

        // 4.创建预编译的PreparedStatement,传入SQL语句
        PreparedStatement ps = con.prepareStatement(sql);

        // 5.获取当前系统执行用时
        long start = System.currentTimeMillis();
        // 获取当前系统时间(毫秒值)
        for (int i = 0; i < 10000; i++) {
            // 5.为占位符赋值
            ps.setString(1,"jack"+i);
            ps.setDouble(2,100.0+i);
            ps.setInt(3,27+i);

            ps.executeUpdate();
        }
        long end = System.currentTimeMillis();
        System.out.println("消耗时间:"+(end-start));
        con.close();
    }

② 批量进行添加

        1.批量操作必须是values,不能是value
        2.必须在链接数据库的URL后面加?rewriteBatchedStatements=true,允许批量操作
        3.调用addBatch()方法,将SQL语句进行批量添加的操作
        4.统一执行批量操作,调用executeBatch()方法

    @Test
    public void testBatch() throws Exception{
        // 1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        // 2.获取链接
        Connection con = DriverManager.getConnection("jdbc:mysql:///javawebjdbc?rewriteBatchedStatements=true","root","954926928lcl");

        // 3.编写sql语句
        // ① 批量操作必须是values,不能是value
        // ② 必须在链接数据库的URL后面加?rewriteBatchedStatements=true,允许批量操作
        // ③ 调用addBatch()方法,将SQL语句进行批量添加的操作
        // ④ 统一执行批量操作,调用executeBatch()方法

        String sql = "insert into t_emp(emp_name,emp_salary,emp_age) values(?,?,?)";

        // 4.创建预编译的PreparedStatement,传入SQL语句
        PreparedStatement ps = con.prepareStatement(sql);
        // 5.获取当前系统执行用时
        long start = System.currentTimeMillis();
        // 获取当前系统时间(毫秒值)
        for (int i = 0; i < 10000; i++) {
            // 5.为占位符赋值
            ps.setString(1,"jack"+i);
            ps.setDouble(2,100.0+i);
            ps.setInt(3,27+i);
            // 若要批量操作,就不要进行executeUpdate()操作,将?看作一个整体,添加一个批处理方法addBatch
//            ps.executeUpdate();
            ps.addBatch();
        }
        // 6.执行批量操作
        // 统一执行批量操作,调用executeBatch()方法
        ps.executeBatch();
        long end = System.currentTimeMillis();
        System.out.println("消耗时间:"+(end-start));
        con.close();
    }

二、连接池

1.现有问题

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

2.连接池

        ① 连接池就是数据库连接对象的缓冲区,通过配置,由连接池负责创建连接、管理连接、释放连接等操作。

        ② 预先创建数据库连接放入连接池,用户在请求时,通过池直接获取连接,使用完毕后,将连接放回池中,避免了频繁的创建和销毁,同时解决了创建的效率

        ③ 当池中无连接可用,且未达到上限时,连接池会新建连接池中连接达到上限,用户请求会等待,可以设置超时时间。

3.常见连接池

        JDBC的数据库连接池使用 javax.sql.DataSource接口进行规范,所有的第三方连接池都实现此接口,自行添加具体实现,也就是说,所有连接池获取连接的和回收连接方法都一样,不同的只有性能和扩展功能
                ① DBCP 是Apache提供的数据库连接池,速度相对C3P0较快,但自身存在一些BUG

                ② C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。

                ③ Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点

                ④ Druid 是阿里提供的数据库连接池,是集DBCP、C3P0、Proxool优点于一身的数据库连接池,性能、扩展性、易用性都更好,功能丰富。

                ⑤ Hikari(ひかり[shi ga li])取自日语,是光的意思,是SpringBoot2.x之后内置的一款连接池,基于 BoneCP(已经放弃维护,推荐该连接池)做了不少的改进和优化,口号是快速、简单、可靠。

4.Druid连接池使用

使用步骤:

        ① 引入jar包(第三方文件)

        ② 编码

硬编码

    @Test
    public void testHardCodeDruid() throws SQLException {
        /*
            硬编码:将连接池的配置信息与Java代码耦合在一起
                1.创建一个DruidDataSource连接池对象
                2.设置连接池的配置信息【必须项|非必须项】
                3.通过连接池获取链接对象
                4.回收链接【将连接归还给连接池,交给其他线程继续使用】
         */

        // 1.创建一个DruidDataSource连接池对象
        DruidDataSource ds = new DruidDataSource();

        // 2.设置连接池的配置信息【必须项|非必须项】
        // 2.1 必须设置的配置
        ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds.setUrl("jdbc:mysql:///javawebjdbc");
        ds.setUsername("root");
        ds.setPassword("954926928lcl");

        // 2.2 非必须设置的配置
        ds.setInitialSize(9); // 初始化大小,只要创建连接池,连接池中就会有9个链接对象
        ds.setMaxActive(18); // 可以设置最大的连接池对象数目是多少

        // 3.通过连接池获取链接对象
        // 获取链接对象语句通用型
        Connection conn = ds.getConnection();
        System.out.println(conn);

        // 4.基于链接对象conn进行增删改查操作

        // 5.回收链接【将连接归还给连接池,交给其他线程继续使用】
        conn.close();
    }

软编码

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

    @Test
    public void testResourcesDruid() throws Exception {
        // 1.创建Properties集合,用于存储外部配置文件的key和value值
        Properties props = new Properties();

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

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

        // 4.通过连接池获取链接对象
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
        
        // 5.开发CRUD

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

软编码的方式可以从properties配置文件中直接更改,有利于我们对代码的更新和维护

5.HikariCP连接池使用

使用步骤

        ① 引入jar包(第三方文件)

        ② 编码

硬编码

    @Test
    public void testHardCodeHikari() throws Exception {
        /*
            硬编码:将连接池的配置信息与Java代码耦合在一起
                1.创建一个HikariDataSource连接池对象
                2.设置连接池的配置信息【必须项|非必须项】
                3.通过连接池获取链接对象
                4.回收链接【将连接归还给连接池,交给其他线程继续使用】
         */
        // 1.创建一个HikariDataSource连接池对象
        HikariDataSource hs = new HikariDataSource();

        // 2.设置连接池的配置信息【必须项|非必须项】
        // 2.1 必须设置的配置
        hs.setDriverClassName("com.mysql.cj.jdbc.Driver");
        hs.setJdbcUrl("jdbc:mysql:///javawebjdbc");
        hs.setUsername("root");
        hs.setPassword("954926928lcl");

        // 2.2 非必须设置的配置
        hs.setMaximumPoolSize(18);
        hs.setMinimumIdle(9);

        // 3.通过连接池获取链接对象
        Connection con = hs.getConnection();
        System.out.println(con);

        // 4.回收连接
        con.close();
    }

软编码

    @Test
    public void testResourcesHikari() throws Exception {
        // 1.创建Properties集合,用于存储外部配置文件的key和value值
        Properties props = new Properties();

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

        // 只有第三步、第四步与Druid连接池不同,其他步骤差不多
        // 3.创建一个HikariConfig连接池配置对象,将Properties集合传进去
        HikariConfig hkcg = new HikariConfig(props);

        // 4.基于HikariConfig连接池配置对象,构建HikariDataSource
        HikariDataSource hkds = new HikariDataSource(hkcg);

        // 5.获取链接
        Connection con = hkds.getConnection();
        System.out.println(con);

        // 6.回收连接
        con.close();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2116088.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(详细文档)javaswing学生成绩管理系统(mysql)+详细报告

摘要 在现今信息时代&#xff0c;生活速度的加快&#xff0c;使得人们越来越向信息化、数字化发展。 随着学校的规模不断扩大&#xff0c;学生数量急剧增加&#xff0c;有关学生的各种信息量也成倍增 长&#xff0c;尤其是学生的考试成绩数据。面对庞大的学生的成绩&#xff0…

@Value读取properties中文乱码解决方案

前几天碰到使用Value中文乱码的问题&#xff0c;英文字符则不会出现问题 原因&#xff1a;SpringBoot在加载properties配置文件时&#xff0c;使用的默认编码是&#xff1a;ISO_88599_1 解决方式&#xff1a;将properties改成yml就可以读取成功了 Data Component PropertySou…

数据结构(邓俊辉)学习笔记】排序 1——快速排序:算法A

文章目录 1. 分而治之2. 轴点3. 构造轴点4. 单调性 不变性5. 实例 1. 分而治之 主题就是排序。实际上我们对于排序问题并不陌生。你应该记得在最开始的几章&#xff0c;我们就分别介绍过起泡排序、插入排序、选择排序以及归并排序&#xff0c;而在介绍散列技术时&#xff0c;我…

Tableau 2023下载安装教程最新教学附软件包百度网盘分享链接地址

Tableau 2023介绍 Tableau 2023下载安装教程最新教学附软件包百度网盘分享链接地址&#xff0c;Tableau 是一款强大的数据可视化软件。它能连接多种数据源并整合&#xff0c;操作简单&#xff0c;通过拖放即可创建可视化报表和仪表盘。具有高效的分析处理能力&#xff0c;支持…

windows下安装并使用nvm

目录 一.准备工作&#xff1a;卸载node 卸载步骤 二.下载nvm 三.安装nvm 三.配置下载源【重要】 四.使用nvm安装node.js 五.nvm常用命令 六.卸载nvm 一.准备工作&#xff1a;卸载node 如果电脑上已经有node&#xff0c;那么我们需要先完全卸载node&#xff0c;再安装…

LeetCode 热题 100 回顾15

干货分享&#xff0c;感谢您的阅读&#xff01;原文见&#xff1a;LeetCode 热题 100 回顾_力code热题100-CSDN博客 一、哈希部分 1.两数之和 &#xff08;简单&#xff09; 题目描述 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标…

FastAPI模块化:为复杂应用程序提供清晰的结构

开题描述&#xff1a; 在现代软件开发中&#xff0c;随着应用程序规模的扩大和功能的增加&#xff0c;传统的单体架构逐渐暴露出其局限性。FastAPI&#xff0c;作为一款高性能的现代Web框架&#xff0c;通过其模块化设计提供了一种解决方案。本文将探讨FastAPI模块化如何为构建…

顶刊中的树状图如何绘制?|科研绘图·24-09-07

小罗碎碎念 本期推文主题&#xff1a;树状图 本期推文主要介绍如何绘制树状图以及它的一些变体形式&#xff0c;看完本篇推文&#xff0c;你最终能够实现的效果如下。 一、组织结构图 Dendrogram是一种网络结构&#xff0c;由一个根节点开始&#xff0c;该节点通过边或分支连接…

找商业网字体加密(TTFont方法)

网点地址&#xff1a;公司介绍-泰州名列新材料有限公司 (zhaosw.com) 问题如下&#xff1a; 在网站中看到的电话号码在页面源码中无法查看 破解步骤&#xff1a; 1.找到woff文件 查找字体的class属性&#xff0c;全文查找font-face-encrypted找到如下内容&#xff0c;可以看到…

在 Linux 上部署javaWeb项目+图文详解_java web项目部署到linux服务器

-f : force强制的意思&#xff0c;如果目标文件已经存在&#xff0c;不会询问直接覆盖 -i : 若目标已经存在&#xff0c;就会询问是否覆盖 -u : 若目标文件已经存在&#xff0c;且比目标文件新&#xff0c;才会更新 # 该命令可以把多个文件一次移动到一个文件夹中&#xff0c;但…

github删除自己创建的仓库

1.进入仓库&#xff0c;点击Settings 2.下拉至Danger Zone区域&#xff0c;点击Delete this repository 3.点击 I want to delete this repository 4.点击i have read ... 5.按提示输入&#xff0c;点击Delete this repository 总结 1.进入仓库&#xff0c;点击Settings 2.下…

推荐9个不同风格的音频频谱波形 听音乐怎么能少了它

9个不同风格的音频频谱波形 听音乐怎么能少了它。在我们沉静在听音乐的过程中&#xff0c;桌面上的频谱跳动&#xff0c;会让音乐更有动感&#xff0c;视觉化把音频表现出来。在桌面上跳动的音乐&#xff0c;更有氛围。小小编给大家带来了9种非常有特殊的音频频谱&#xff0c;看…

做一个最简单的CPU -- 计算机组成原理(六)

在上一个章节中&#xff0c;我们已经了解了一个存储是如何制作出来的&#xff0c;利用这个存储我们就可以做一个最简单的CPU 指令 我们知道CPU负责执行计算机的程序&#xff0c;而程序其实是一个个的操作指令 比如可能是计算指令&#xff0c;cpu会指示ALU进行加减运算 也可…

【web网页制作】html+css旅游家乡河南主题网页制作(5页面)【附源码】

一、&#x1f468;‍&#x1f393;网站题目 旅游&#xff0c;当地特色&#xff0c;历史文化&#xff0c;特色小吃等网站的设计与制作。 二、✍️网站描述 &#x1f468;‍&#x1f393;静态网站的编写主要是用HTML DIVCSS 等来完成页面的排版设计&#x1f469;‍&#x1f393;…

Leetcode面试经典-115.不同的子序列

解法都在代码里&#xff0c;不懂就留言或者私信 理论上提交这个就是最优解 class Solution {public int numDistinct(String s, String t) {if(s.length() < t.length()) {return 0;}if(s.length() t.length()) {return s.equals(t)? 1 : 0;}char[] sArr s.toCharArray…

【大模型基础】P2 Bag-of-Words 词袋模型

目录 词袋模型 概述词袋模型 实例第1步 构建语料库第2步 对句子进行分词第3步 创建词汇表第4步 转换词袋表示第5步 计算余弦相似度 词袋模型的局限性 词袋模型 概述 词袋模型&#xff0c;Bag-of-Words&#xff0c;是一种简单的文本表示方法&#xff0c;也是 NLP 中的一个经典模…

(计算机论文)基于C#、Unity的先行者技能熟练度游戏系统的设计与实现

毕业设计&#xff08;论文&#xff09; ​​​​​ ​博主可接毕设论文&#xff01;&#xff01;&#xff01; 论文题目&#xff1a;基于C#、Unity的先行者技能熟练度游戏系统的设计与实现 摘 要 随着数字娱乐产业的蓬勃发展&#xff0c;独立游戏因其创新性和独特…

5.【Java开发手册】| 异常日志

这里我就列出一些我认为应当遵守的&#xff0c;并且添加一些我自己在工作中的一些感受&#xff0c;如果照着文档抄&#xff0c;那完全变成练习打字了&#xff0c;浪费读者时间&#xff0c;如果你也认同我的看法&#xff0c;或者和我有类似感受&#xff0c;可以点个关注&#xf…

【Java 优选算法】双指针(上)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 移动零 分析 代码 复写零 分析 代码 快乐数 分析 代码 盛最多水的容器 分析 代码 移动零 题目链接 分析 双指针算法,利用两个指针cur和dest将数组划分为三个区间…

Java题集综合实践——简易计算器制作

此系列文章收录大量Java经典代码题&#xff08;也可以算是leetcode刷题指南&#xff09;&#xff0c;剩余文章指路Java题集。希望可以与大家一起探索Java的神秘。3、2、1&#xff0c;请看&#xff01; 本篇文章将带大家编写一个简易算术计算器。 功能&#xff1a;将几个算术功…