JDBC学习笔记(二)进阶篇

一、JDBC 扩展

1.1 实体类和ROM

实体类代码:

package com.atguigu.advanced.pojo;

//类名就是数据库表的 t_ 后面的单词全写
public class Employee {

    private Integer empId;//emp_id
    
    private String empName;//emp_name
    
    private Double empSalary;//emp_salary
    
    private Integer empAge;//emp_age


    /**
     * 设置 无参、有参、get、set、toString 方法
     */
    public Employee() {
    }

    public Employee(Integer empId, String empName, Double empSalary, Integer empAge) {
        this.empId = empId;
        this.empName = empName;
        this.empSalary = empSalary;
        this.empAge = empAge;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Double getEmpSalary() {
        return empSalary;
    }

    public void setEmpSalary(Double empSalary) {
        this.empSalary = empSalary;
    }

    public Integer getEmpAge() {
        return empAge;
    }

    public void setEmpAge(Integer empAge) {
        this.empAge = empAge;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", empSalary=" + empSalary +
                ", empAge=" + empAge +
                '}';
    }
}

ORM:

ORM:

以面向对象的思想去操作数据库。

即:一张表对应一个类,一行数据对应一个对象,一个列对应一个属性

package com.atguigu.advanced;

import com.atguigu.advanced.pojo.Employee;
import org.junit.Test;

import java.sql.*;
import java.util.ArrayList;

public class JDBCAdvanced {

    /**
     * 什么是ORM
     * @throws Exception
     */
    @Test
    public void testORM() throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.创建连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");

        //3.获取PreparedStatement对象,执行SQL语句
        PreparedStatement preparedStatement = connection.prepareStatement("select * from t_emp where emp_id = ?");

        //4.为占位符赋值,然后执行并返回结果集
        preparedStatement.setInt(1,1);
        ResultSet resultSet = preparedStatement.executeQuery();

        //创建对象
        Employee employee = null;

        //5.处理结果,遍历resultSet
        if (resultSet.next()){
            employee = new Employee();
            int empId = resultSet.getInt("emp_id");
            String empName = resultSet.getString("emp_name");
            double empSalary = resultSet.getDouble("emp_salary");
            int empAge = resultSet.getInt("emp_age");
            //为对象的属性赋值
            employee.setEmpId(empId);
            employee.setEmpName(empName);
            employee.setEmpSalary(empSalary);
            employee.setEmpAge(empAge);

        }

        System.out.println(employee);

        //6.释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();


    }

    @Test
    public void testORMList() throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");

        //3.执行SQL语句,获取PreparedStatement对象
        PreparedStatement preparedStatement = connection.prepareStatement("select * from t_emp");

        //4.执行并接收返回的,结果集
        ResultSet resultSet = preparedStatement.executeQuery();

        //对象的创建
        Employee employee = null;

        ArrayList<Employee> employeeList = new ArrayList<>();

        //5.处理结果集,遍历resultSet
        while (resultSet.next()){
            employee = new Employee();
            int empId = resultSet.getInt("emp_id");
            String empName = resultSet.getString("emp_name");
            double empSalary = resultSet.getDouble("emp_salary");
            int empAge = resultSet.getInt("emp_age");

            //为对象属性赋值
            employee.setEmpId(empId);
            employee.setEmpName(empName);
            employee.setEmpSalary(empSalary);
            employee.setEmpAge(empAge);
            //将每次循环封装的一行数据的对象存储在集合里
            employeeList.add(employee);
        }

        //处理结果:遍历集合
        for (Employee emp : employeeList){
            System.out.println(emp);
        }


        //6.释放资源
        resultSet.close();
        preparedStatement.close();
        connection.close();


    }
}

1.2 主键回显

主键回显:

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

/**
     * 主键回显(主键回填)
     * @throws Exception
     */
    @Test
    public void testKP() throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");

        //3.预编译SQL语句,获取PreparedStatement对象;告知preparedStatement,返回新增数据的主键列的值
        String sql = "INSERT INTO t_emp(emp_name,emp_salary,emp_age) VALUES (?,?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS);

        //创建对象,将对象的属性值,填充在?占位符上(ORM)
        Employee employee = new Employee(null,"jack",123.45,29);
        preparedStatement.setString(1, employee.getEmpName());
        preparedStatement.setDouble(2,employee.getEmpSalary());
        preparedStatement.setInt(3,employee.getEmpAge());

        //4.执行SQL,并获取返回的结果
        int result = preparedStatement.executeUpdate();

        //5.处理结果
        ResultSet resultSet = null;
        if(result > 0){
            System.out.println("成功!");

            //获取当前新增数据的主键列,回显到Java中employee对象的empId属性上
            //返回的结果值,是一个单行单例的结果存储在ResultSet里
            resultSet = preparedStatement.getGeneratedKeys();
            if (resultSet.next()){
                int empId = resultSet.getInt(1);
                employee.setEmpId(empId);
            }
            System.out.println(employee);
        }else {
            System.out.println("失败!");
        }

        //6.释放资源
        //避免空指针异常
        if (resultSet != null){
            resultSet.close();
        }
        preparedStatement.close();
        connection.close();
    }

1.3 批量操作

1、插入多条数据时,一条一条发送给数据库执行,效率低下

2、通过批量操作,可以提升多次操作效率

没有批量操作的代码

/**
     * 没有批量操作的代码
     * @throws Exception
     */
    @Test
    public void testMoreInsert() throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu", "root", "123456");

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

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

        //获取当前代码执行的时间,毫秒值
        //开始的时间
        long start = System.currentTimeMillis();
        for (int i=0;i<10000;i++){
            //5.为占位符赋值
            preparedStatement.setString(1,"marry"+i);
            preparedStatement.setDouble(2,100.0+i);
            preparedStatement.setInt(3,20+i);

            preparedStatement.executeUpdate();
        }
        //获取当前代码执行结束的时间,毫秒值
        long end = System.currentTimeMillis();

        System.out.println("消耗时间:"+ (end - start));

        //6.释放资源
        preparedStatement.close();
        connection.close();
    }

有批量操作的代码

/**
     * 有批量操作的代码
     * @throws Exception
     */
    @Test
    public void testBatch() throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.cj.jdbc.Driver");

        //2.获取连接
        Connection connection = DriverManager.getConnection("jdbc:mysql:///atguigu?rewriteBatchedStatements=true", "root", "123456");

        //3.编写SQL语句
        /*
            【注意】:
                    1.必须在连接数据库的URL后面追加?rewriteBatchedStatements=true,允许批量操作
                    2.新增SQL必须用values,且语句最后不要追加;结束
                    3.调用addBatch() 方法,将SQL语句进行批量添加操作
                    4.统一执行批量操作,调用executeBatch()
         */
        String sql  = "insert into t_emp (emp_name,emp_salary,emp_age) values (?,?,?)";

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

        //获取当前代码执行的时间,毫秒值
        //开始的时间
        long start = System.currentTimeMillis();
        for (int i=0;i<10000;i++){
            //5.为占位符赋值
            preparedStatement.setString(1,"marry"+i);
            preparedStatement.setDouble(2,100.0+i);
            preparedStatement.setInt(3,20+i);

            preparedStatement.addBatch();
        }

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

        //获取当前代码执行结束的时间,毫秒值
        long end = System.currentTimeMillis();

        System.out.println("消耗时间:"+ (end - start));

        //6.释放资源
        preparedStatement.close();
        connection.close();
    }

二、连接池

2.1 现有问题

2.2 连接池

2.3 常见连接池

 

 

2.4 Druid 连接池使用

1、使用步骤

  • 引入 jar 包
  • 编码

2、代码实现 - 硬编码方式(了解)

把连接池的配置和Java代码耦合到一起,不利于更新(更改)、维护

/**
     * Druid 硬编码
     * @throws Exception
     */
    @Test
    public void testHardCodeDruid() throws Exception{
        /*
            硬编码:将连接池的配置信息和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:///atguigu");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("123456");

        //2.2 非必须设置的配置
        druidDataSource.setInitialSize(10);
        druidDataSource.setMaxActive(20);

        //3.通过连接池获取连接对象
        //DruidPooledConnection extends PoolableWrapper implements PooledConnection, Connection
        DruidPooledConnection connection = druidDataSource.getConnection();

        //基于connection进行CRUD

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


    }

3、代码实现 - 软编码方式(推荐⭐)

把连接池的配置提取出来放到配置文件里,把配置文件和 Java 代码解耦,好处是利于维护和更改。

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

/**
     * 软编码
     * @throws Exception
     */
    @Test
    public void testResourcesDruid() throws Exception {
        //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();
        System.out.println(connection);

        //5.开发CRUD

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

2.5 HikariCP 连接池使用

1、硬编码

/**
     * Hikari 硬编码
     * @throws Exception
     */
    @Test
    public void testHardCodeHikari() throws Exception{
        /*
            硬编码:将连接池的配置信息和Java代码耦合在一起
                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:///atguigu");
        hikariDataSource.setUsername("root");
        hikariDataSource.setPassword("123456");

        //2.2 非必须设置的配置
        hikariDataSource.setMinimumIdle(10);
        hikariDataSource.setMaximumPoolSize(20);

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

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

2、软编码

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

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

        //3.创建HikariConfig连接池配置对象,将Properties集合传进去
        HikariConfig hikariConfig = new HikariConfig(properties);

        //4.基于HikariCofig连接池配置对象,构建HikariDataSource
        HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);

        //5.获取连接
        Connection connection = hikariDataSource.getConnection();
        System.out.println(connection);

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二叉树遍历 和 线索二叉树

文章目录 1.1 二叉树遍历1.1 前提问题1&#xff1a; 什么叫二叉树的遍历&#xff1f;二叉树的三种遍历&#xff1a;三个概念&#xff1a;遍历 和 访问 和 经过重要概念&#xff1a;遍历过程中的经过节点&#xff0c;不代表访问节点 问题2&#xff1a;遍历和访问的联系&#xff…

利用conda进行R的安装

1.miniconda3的安装 官网&#xff1a;Miniconda — Conda documentation 找到对应系统、Python版本下载 wget https://mirrors.ustc.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh #wget -c https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x…

Python项目代码太多if-else? 这样优化才优雅!

前言 代码中不可避免地会出现复杂的if-else条件逻辑,而简化这些条件表达式是一种提高代码可读性极为实用的技巧。 在 Python 中,有多种方法可以避免复杂的 if-else 条件逻辑,使代码更加清晰和易于维护。 筑基期 提前 return,去掉多余的 else 在 Python 中,使用"提…

C++基础编程100题-003 OpenJudge-1.1-05 输出保留12位小数的浮点数

更多资源请关注纽扣编程微信公众号 http://noi.openjudge.cn/ch0101/05/ 描述 读入一个双精度浮点数&#xff0c;保留12位小数&#xff0c;输出这个浮点数。 输入 只有一行&#xff0c;一个双精度浮点数。 输出 也只有一行&#xff0c;保留12位小数的浮点数。 样例输入…

Day 42 LVS四层负载均衡

一&#xff1a;负载均衡简介 1.集群是什么 ​ 集群&#xff08;cluster&#xff09;技术是一种较新的技术&#xff0c;通过集群技术&#xff0c;可以在付出较低成本的情况下获得在性能、可靠性、灵活性方面的相对较高的收益&#xff0c;其任务调度则是集群系统中的核心技术 …

LangChain学习之 Question And Answer的操作

1. 学习背景 在LangChain for LLM应用程序开发中课程中&#xff0c;学习了LangChain框架扩展应用程序开发中语言模型的用例和功能的基本技能&#xff0c;遂做整理为后面的应用做准备。视频地址&#xff1a;基于LangChain的大语言模型应用开发构建和评估。 2. Q&A的作用 …

web刷题记录(2)

[鹤城杯 2021]EasyP 就是php的代码审计 从中可以看出来&#xff0c;就是对四个if语句的绕过&#xff0c;然后过滤了一些语句 代码分析&#xff1a; 通过include utils.php;导入了一个叫做"utils.php"的文件&#xff0c;这意味着在该文件中可能定义了一些与本代码相…

通信协议:常见的芯片间通信协议

相关阅读 通信协议https://blog.csdn.net/weixin_45791458/category_12452508.html?spm1001.2014.3001.5482 本文将简单介绍一些常见的芯片间通信协议&#xff0c;但不会涉及到协议的具体细节。首先说明&#xff0c;芯片间通信方式根据通信时钟的区别可以分为&#xff1a;异步…

计算机网络ppt和课后题总结(上)

试在下列条件下比较电路交换和分组交换。要传送的报文共 x(bit)。从源点到终点共经过 k 段链路&#xff0c;每段链路的传播时延为 d(s)&#xff0c;数据率为 b(b/s)。在电路交换时电路的建立时间为 s(s)。在分组交换时分组长度为 p(bit)&#xff0c;且各结点的排队等待时间可忽…

基于YOLOv7的口罩检测

目录 1. 作者介绍2. YOLOv7网络模型2.1 算法简介2.2 数据集介绍2.3 YOLO格式数据集制作 3. 代码实现3.1 分割数据集3.2 修改数据配置文件3.3 修改训练代码&#xff0c;进行训练3.4 修改测试代码&#xff0c;进行测试3.5 检测结果 1. 作者介绍 曹宇欢&#xff0c;女&#xff0c…

跨越国界, 纷享销客助力企业全球业务增长

出海&#xff0c;已不再是企业的“备胎”&#xff0c;而是必须面对的“大考”&#xff01;在这个全球化的大潮中&#xff0c;有的企业乘风破浪&#xff0c;勇攀高峰&#xff0c;也有的企业在异国他乡遭遇了“水土不服”。 面对“要么出海&#xff0c;要么出局”的抉择&#xff…

盲盒风尚:拆盒吧引领新潮消费趋势

在当下这个快速变化的消费时代&#xff0c;拆盒吧以其独特的盲盒经济模式&#xff0c;成为了新潮文化消费的引领者。不同于传统的购物方式&#xff0c;拆盒吧通过创新的玩法和多元化的产品线&#xff0c;为消费者带来了前所未有的购物体验。 一、拆盒吧&#xff1a;解锁盲盒新玩…

现代密码学-国密算法

商用密码算法种类 商用密码算法 密码学概念、协议与算法之间的依赖关系 数字签名、证书-公钥密码、散列类算法 消息验证码-对称密码 &#xff0c;散列类 安全目标与算法之间的关系 机密性--对称密码、公钥密码 完整性--散列类算法 可用性--散列类、公钥密码 真实性--公…

数据结构之初始泛型

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 目录 深入了解包装类 包装类的由来 装箱与拆箱 面试题 泛型 泛型的语法与使用…

可长期操作的赚钱项目,时间自由,但不适合大学生

如何评价现在的csgo市场&#xff1f; 可长期操作的赚钱项目&#xff0c;时间自由&#xff0c;但不适合大学生。 都在问&#xff0c;有哪些可以长期做下去的赚钱项目&#xff0c;童话就不拐弯抹角了&#xff0c;csgo/steam游戏搬砖一定是最适合长期做下去的赚钱项目。 不说别人…

CondaSSLError: OpenSSL appears to be unavailable on this machine.

conda create -n x1 python3.7报错 PS C:\Users\Richardo.M.Song\Desktop\lele_seg\x1> conda create -n x1 python3.7 Collecting package metadata (current_repodata.json): failed CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is requ…

Varnish讲解文章、缓存代理配置、核心功能、优势、Varnish在什么情况下会选择缓存哪些类型的内容、Varnish如何实现负载均衡功能?

varnish官网链接 Varnish文章概览 Varnish是一款高性能的HTTP加速器&#xff08;web应用加速器&#xff09;&#xff0c;是一款开源软件&#xff0c;它能够显著提高网站的响应速度和减少服务器的负载。Varnish的设计理念是利用缓存技术&#xff0c;将频繁访问的静态内容存储在…

【Python】 探索Pytz库中的时区列表

基本原理 在Python中&#xff0c;处理时区是一个常见但复杂的问题。pytz是一个Python库&#xff0c;它提供了对时区的精确和丰富的支持。pytz库是datetime模块的补充&#xff0c;它允许更准确地处理时区信息。pytz库包括了IANA时区数据库&#xff0c;这个数据库包含了全球的时…

13-至少有5名直接下属的经理(高频 SQL 50 题基础版)

13-至少有5名直接下属的经理 select name from Employee where id in (select managerId -- 查找大于5的经理idfrom Employeegroup by managerId -- 根据id分组having count(*)>5); -- 根据分组的数据进行求个数

小白级教程—安装Ubuntu 20.04 LTS服务器

下载 本教程将使用20.04版进行教学 由于官方速度可能有点慢&#xff0c;可以下方的使用清华镜像下载 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/ 点击20.24版本 选择 ubuntu-20.04.6-live-server-amd64.iso 新建虚拟机 下载好后 我们使用 VMware 打开它 这里选…