JDBC学习笔记(二)进阶篇

news2024/12/26 9:32:39

一、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();
    }

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

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

相关文章

FL Studio 21.2.3.4004官方中文破解版下载安装激活教程重磅发布含注册机

今天带来的是FL Studio 21中文版&#xff0c;内置破解补丁&#xff0c;可以完美激活程序。所有功能均可在线编辑&#xff0c;用户可直接操作。同时&#xff0c;因为FL Studio 21是最新版本&#xff0c;所以增加了新的功能。共有八种乐器和效果器插件&#xff0c;包括效果链、音…

在开源处理器架构RISC-V中发现可远程利用的中危漏洞

在RISC-V SonicBOOM处理器设计中发现中度危险的漏洞 最近&#xff0c;西北工业大学的网络空间安全学院胡伟教授团队在RISC-V SonicBOOM处理器设计中发现了一个中度危险的漏洞。这个团队的研究人员发现了一个可远程利用的漏洞&#xff0c;该漏洞存在于开源处理器架构RISC-V中。…

Redis系列-4 Redis集群介绍

Redis集群 Redis提供了持久化能力&#xff0c;保证了重启不会丢失数据&#xff1b;但Redis重启至完全恢复期间&#xff0c;缓存不可用。另外&#xff0c;对于高并发场景下&#xff0c;单点Redis服务器的性能不能满足吞吐量要求&#xff0c;需要进行横向扩展。此时&#xff0c;…

【适配鸿蒙next】Flutter 新一代混合栈管理框架

前言 据最新消息显示&#xff0c;华为今年下半年将全面转向其自主平台HarmonyOS&#xff0c;放弃Android系统。 报道中提到&#xff0c;下一版HarmonyOS预计将随华为即将推出的Mate 70旗舰系列一起发布。 据悉&#xff0c;HarmonyOS Next 已经扩展到4000个应用程序&#xff0c;…

【Python学习1】matplotlib和pandas库绘制人口数变化曲线

✍&#x1f3fb;记录学习过程中的输出&#xff0c;坚持每天学习一点点~ ❤️希望能给大家提供帮助~欢迎点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;指点&#x1f64f; 一、Python库说明 Matplotlib Matplotlib是一个功能强大的Python 2D绘图库&#xff0c;它允…

【实战项目二】Python爬取豆瓣影评

目录 一、环境准备 二、编写代码 一、环境准备 pip install beautifulsoup4 pip intall lxml pip install requests我们需要爬取这些影评 二、编写代码 我们发现每个影评所在的div的class都相同&#xff0c;我们可以从这入手 from bs4 import BeautifulSoup import request…

修改云主机配置 - 内存增容

文章目录 一、修改云主机配置缘由二、修改云主机配置步骤1、查看云主机概述2、查看master云主机3、更改master云主机配置4、查看master云主机 三、使用Spark Shell玩Saprk SQL1、启动HDFS服务2、启动Spark集群3、启动集群模式Spark Shell4、读取文件生成单例数据帧5、将单列数据…

给浮躁的面试者一个建议

哈喽&#xff0c;大家好&#xff0c;我叫人宅&#xff0c;关于找工作&#xff0c;大家心态非常浮躁&#xff0c;尤其是零零后&#xff0c;或者是九五后。本次为大家分享一下关于就业问题和就业态度。 我讲解的这些其实适合所有高科技行业。我这边就拿程序员为例。 如果你是刚毕…

Python Mistune库:Markdown解析和处理

更多Python学习内容&#xff1a;ipengtao.com Mistune是一个用于Python的快速且功能强大的Markdown解析库。它以其高性能和灵活性著称&#xff0c;能够轻松扩展和定制。Mistune支持标准的Markdown语法&#xff0c;并且可以通过插件扩展支持更多功能&#xff0c;例如数学公式、高…

云服务器Ubuntu系统的vim-plus(youcompleteme)完整安装

一. 安装vim-plus PS&#xff1a;需要在那个用户下配置vim-plus&#xff0c;就到那个用户下执行代码 git clone https://github.com/chxuan/vimplus.git ~/.vimplus cd ~/.vimplus ./install.sh二. 解决没有代码自动补全的问题 随便创建一个Test.cpp文件&#xff0c;vim打开…

线性代数|机器学习-P10最小二乘法的四种方案

文章目录 1. 概述2. SVD奇异值分解3. 最小二乘法方程解4. 最小二乘法图像解释5. Gram-Schmidt 1. 概述 当我们需要根据一堆数据点去拟合出一条近似的直线的时候&#xff0c;就会用到 最小二乘法 .根据矩阵A的情况&#xff0c;有如下四种方法 在r n m 时&#xff0c;SVD奇异…

Apple - Quartz 2D Programming Guide

本文翻译自&#xff1a;Quartz 2D Programming Guide&#xff08;更新时间&#xff1a;2017-03-21 https://developer.apple.com/library/archive/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/Introduction/Introduction.html#//apple_ref/doc/uid/TP300010…

SpringCloud中注册中心Nacos的下载与使用步骤

1.前言 Nacos&#xff08;Dynamic Naming and Configuration Service&#xff09;是阿里巴巴开源的一款服务发现和配置管理工具。它可以帮助用户自动化地进行服务注册、发现和配置管理&#xff0c;是面向微服务架构的一个重要组成部分。 2.下载 链接&#xff1a;https://pan.b…

002-链路聚合

链路聚合 链路聚合是一个重要的计算机网络术语&#xff0c;它涉及将多个物理端口汇聚在一起&#xff0c;形成一个逻辑端口&#xff0c;从而增加网络带宽、实现链路传输的弹性和工程冗余。 定义与基本原理 定义&#xff1a;链路聚合&#xff08;英语&#xff1a;Link Aggrega…

6.7-6.10作业

1. /*1.使用switch实现银行系统&#xff0c;默认用户为A&#xff0c;密码为1234&#xff0c;余额2000 如果登录失败&#xff0c;则直接结束 如果登录成功&#xff0c;则显示银行页面 1.查询余额 2.取钱 3.存钱 如果是1&#xff0c;则打印余额 如果是2&#xff0c;则输入取钱金…

纳什均衡:博弈论中的运作方式、示例以及囚徒困境

文章目录 一、说明二、什么是纳什均衡&#xff1f;2.1 基本概念2.2 关键要点 三、理解纳什均衡四、纳什均衡与主导策略五、纳什均衡的例子六、囚徒困境七、如何原理和应用7.1 博弈论中的纳什均衡是什么&#xff1f;7.2 如何找到纳什均衡&#xff1f;7.3 为什么纳什均衡很重要&a…

python 判断点和线段相交

python 判断点和线段相交 import numpy as np import cv2 import numpy as npdef point_to_line_distance(points, line_segments):# line_segments [[549, 303], [580, 303]]# points [565, 304]x0, y0, x1, y1line_segments[0][0], line_segments[0][1], line_segments[1]…

手把手带你做一个自己的网络调试助手(1) - TCP服务器准备

程序设计流程图 TCP 服务器 ui界面搭建 Tcp服务器建立连接 - listen() connect() 1.在构造函数中进行如下初始化: 通过 QNetworkInterface 类的 allAddresses 这一API 获得可用IP地址&#xff08;包括IPv4 和 IPv6&#xff09; 然后通过QHostAddress类的 protocol 这一AP…

前端-a-date-picker如何设置禁选时间段

想要做到如图所示的效果&#xff0c;代码如下&#xff1a; 第一个是只能选择某一天&#xff0c;第二个是只能选择某一个时间段 <a-date-pickerv-model:value"record.onTimeStr":show-time"{ format: HH:mm }"valueFormat"YYYY-MM-DD HH:mm:ss&qu…

【算法小记】深度学习——时间序列数据分析 Time series Data Analysis

在本篇博客中将简单介绍常见的几种循环神经网络和一维卷积神经网络&#xff0c;并使用一些简答的数据进行拟合分析。本文相对适合刚入门的同学&#xff0c;同时也作为自己过去一段时间学习的总结和记录&#xff0c;现在神经网络框架已经非常完善的支持了很多常见和有效的深度学…