当前位置: 首页 > news >正文

JDBC 进阶

 一 实体类和ORM

对指定的对象的属性封装

package com.ax.advance.pojo;

public class Employee {

    private Integer id;
    private String degree;
    private String major;
    private String school1;
    private String school2;
    private String school3;
    private Integer userId;

    public Employee(Integer id, String degree, String major, String school1, String school2, String school3, Integer userId) {
        this.id = id;
        this.degree = degree;
        this.major = major;
        this.school1 = school1;
        this.school2 = school2;
        this.school3 = school3;
        this.userId = userId;
    }

    public Employee() {
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getDegree() {
        return degree;
    }

    public void setDegree(String degree) {
        this.degree = degree;
    }

    public String getMajor() {
        return major;
    }

    public void setMajor(String major) {
        this.major = major;
    }

    public String getSchool1() {
        return school1;
    }

    public void setSchool1(String school1) {
        this.school1 = school1;
    }

    public String getSchool2() {
        return school2;
    }

    public void setSchool2(String school2) {
        this.school2 = school2;
    }

    public String getSchool3() {
        return school3;
    }

    public void setSchool3(String school3) {
        this.school3 = school3;
    }

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", degree='" + degree + '\'' +
                ", major='" + major + '\'' +
                ", school1='" + school1 + '\'' +
                ", school2='" + school2 + '\'' +
                ", school3='" + school3 + '\'' +
                ", userId=" + userId +
                '}';
    }
}

数据封装在对象当中

package com.ax.advance;

import com.ax.advance.pojo.Employee;

import java.sql.*;

public class JDBCa {
    public static void main(String[] args) throws SQLException {
        //获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/itheima", "root", "tan2179432748");
        //预编译SQL语句
        PreparedStatement preparedStatement = connection.prepareStatement("select * from tb_user_edu where degree = ?");
        //为问号占位符赋值,并执行SQL语句,接收返回的结果集
        preparedStatement.setString(1, "本科");
        //处理结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        //遍历结果集
        Employee employee = null;
        while (resultSet.next()) {
            int id = resultSet.getInt("id");
            String degree = resultSet.getString("degree");
            String major = resultSet.getString("major");
            String primaryschool = resultSet.getString("primaryschool");
            String middleschool = resultSet.getString("middleschool");
            String university = resultSet.getString("university");
            int userId = resultSet.getInt("userid");

            //封装对象
            employee = new Employee(id, degree, major, primaryschool, middleschool, university, userId);
            System.out.println(employee);
        }
        //资源的释放(先开后放)
        resultSet.close();
        preparedStatement.close();
        connection.close();

    }
}

对象再封装在集合当中

package com.ax.advance;

import com.ax.advance.pojo.Employee;

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

public class JDBCb {
    public static void main(String[] args) throws SQLException {
        
        //获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/itheima", "root", "tan2179432748");
        
        //预编译SQL语句
        PreparedStatement preparedStatement = connection.prepareStatement("select * from tb_user_edu where degree = ?");
        
        //为问号占位符赋值,并执行SQL语句,接收返回的结果集
        preparedStatement.setString(1, "本科");
        
        //处理结果集
        ResultSet resultSet = preparedStatement.executeQuery();
        
        //创建集合存储对象
        ArrayList<Employee> employees = new ArrayList<>();
        
        //遍历结果集
        Employee employee = null;
        while (resultSet.next()) {
            employee = new Employee();
            employee.setId(resultSet.getInt("id"));
            employee.setDegree(resultSet.getString("degree"));
            employee.setMajor(resultSet.getString("major"));
            employee.setSchool1(resultSet.getString("primaryschool"));
            employee.setSchool2(resultSet.getString("middleschool"));
            employee.setSchool3(resultSet.getString("university"));
            employee.setUserId(resultSet.getInt("userid"));
            employees.add(employee);
        }
        //输出
        employees.forEach(System.out::println);


    }
}

二 主键回显

主键回显指在数据库插入操作后,自动获取数据库生成的主键值(如自增ID、序列值等),并将其回填到程序中的对象或变量中。其核心目的是解决多表关联插入时主键依赖问题,例如:主表插入后需获取自增ID,才能将子表数据的外键关联到该ID

实现目的:有效地处理自动生成的主键值

代码实现

package com.ax.advance;

import com.ax.advance.pojo.Employee2;

import java.sql.*;

public class JDBCc {
    public static void main(String[] args) throws SQLException {
        // 获取连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost/itheima", "root", "tan2179432748");
        // 预编译SQL语句并设置返回主键
        PreparedStatement preparedStatement =
                connection.prepareStatement("insert into ax_new (name, school, age) values (?,?,?)",
                        Statement.RETURN_GENERATED_KEYS);
        //创建对象
        Employee2 employee2 = new Employee2(null, "张三", "清华大学", 20);
        preparedStatement.setString(1, employee2.getName());
        preparedStatement.setString(2, employee2.getSchool());
        preparedStatement.setInt(3, employee2.getAge());
        // 执行SQL语句,返回受影响的行数(这里已经添加了,主键是自动增长的)
        int i = preparedStatement.executeUpdate();

        ResultSet resultSet = null;
        // 判断是否添加成功
        if (i > 0) {
            System.out.println("添加成功");
            //获取当前新增数据的主键列,回显到Java封装的对象Employee2的id属性中,返回结果放在ResultSet中
            resultSet = preparedStatement.getGeneratedKeys();
            while (resultSet.next()) {
                employee2.setId(resultSet.getInt(1));
            }
            System.out.println(employee2);
        } else {
            System.out.println("添加失败");
        }
        //释放资源
        if (resultSet != null) {
            resultSet.close();
        }
        preparedStatement.close();
        connection.close();
        
        
    }
}

三 批量操作

通过合理使用JDBC批量操作,可显著减少网络往返和数据库负载,提升应用性能。

JDBC的批量操作允许一次性执行多个SQL语句,显著提升数据库操作的效率,尤其适用于大量数据插入、更新或删除的场景。

代码实现:

package com.ax.advance;

import java.sql.*;

public class JDBCd {
    public static void main(String[] args) throws SQLException {
        //获取连接对象
        Connection connection = DriverManager.
                getConnection("jdbc:mysql://localhost/itheima?rewriteBatchedStatements=True", "root", "tan2179432748");
        // 预编译SQL语句
        PreparedStatement preparedStatement = connection.prepareStatement("insert into ax_new (name, school, age) values (?,?,?)");

        for (int i = 0; i < 10; i++){
            preparedStatement.setString(1, "ax" + i);
            preparedStatement.setString(2, "清华大学" + i);
            preparedStatement.setInt(3, i);
            // 添加到批处理中
            preparedStatement.addBatch();
        }
        //执行批处理
        preparedStatement.executeBatch();
        //资源释放
        preparedStatement.close();
        connection.close();

    }

}

四 连接池

DBC连接池是一种管理和复用数据库连接的技术,旨在减少频繁创建/关闭连接的开销,提升应用性能。(在每次操作数据库都要获取新连接,使用完毕就close释放,频繁的创建和销毁造成资源浪费,连接的数量无法把控对服务器来说压力巨大。)

  1. 传统JDBC连接的缺点

    • 高开销:每次操作都新建连接,涉及网络握手、身份验证等耗时操作。

    • 资源浪费:频繁开关连接会导致数据库负载过高。

    • 难以应对高并发:大量并发请求时,频繁创建连接会导致性能瓶颈。

  2. 连接池的核心思想

    • 预创建连接:初始化时创建一定数量的连接,放入“池”中。

    • 复用连接:应用从池中借用连接,用完后归还(而非关闭)。

    • 动态管理:根据负载动态调整池中的连接数量。

常见连接池:

1 Druid连接池的使用

硬编码

package com.ax.advance.pool;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import org.junit.jupiter.api.Test;

import java.sql.SQLException;

public class DruidTest {
    @Test
    public void testHardCodeDruid() throws SQLException {
        //创建DruidDataSource对象
        DruidDataSource druidDataSource = new DruidDataSource();

        //设置连接池的配置信息
        //必须
        druidDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        druidDataSource.setUrl("jdbc:mysql://localhost/itheima");
        druidDataSource.setUsername("root");
        druidDataSource.setPassword("tan2179432748");
        //非必须
        druidDataSource.setInitialSize(10);
        druidDataSource.setMaxActive(20);

        //通过连接池获取连接对象
        DruidPooledConnection connection = druidDataSource.getConnection();


        //基于connection进行CRUD


        //回收连接对象(将连接归还给连接池,而不是释放资源)
        connection.close();

    }
}

软编码(不基于maven管理工具)

代码实现:

    @Test
    public void testResourcesDruid() throws Exception {
        // 创建Properties集合,用于存储连接池的配置信息(key和value)
        // Properties 是 Java 中用来处理属性文件的一个类,通常用于加载配置文件中的键值对。
        Properties properties = new Properties();

        // 读取外部配置文件,获取输入流,加载到Properties集合中
        // 使用ClassLoader的getResourceAsStream方法来获取资源的输入流,这样可以确保在任何环境下都能正确找到资源文件。
        // "db.properties" 是一个典型的数据库连接属性文件,其中包含了数据库驱动、URL、用户名、密码等信息。
        InputStream inputStream = DruidTest.class.getClassLoader().getResourceAsStream("db.properties");
        properties.load(inputStream); // 加载输入流中的内容到Properties对象中

        // 创建DruidDataSource对象
        // Druid是一个高效的数据库连接池实现,通过传递Properties对象给createDataSource方法,
        // 我们可以初始化一个包含所有必要配置的连接池。
        DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);

        // 通过连接池获取连接对象
        // getConnection 方法从连接池中获取一个可用的数据库连接,这比直接创建新的数据库连接更加高效。
        Connection connection = dataSource.getConnection();
        System.out.println(connection); // 输出连接对象,通常是调试用

        // 基于connection进行CRUD操作
        // 这里可以根据需要执行查询、插入、更新或删除操作。具体实现依赖于业务逻辑需求。

        // 回收连接对象(将连接归还给连接池,而不是释放资源)
        // 调用close方法并不是真的关闭连接,而是将连接返回到连接池中,以便后续使用。
        connection.close();
    }

2 Hikari连接池的使用(省略-后期补充)

相关文章:

  • vulnhub靶场之【kioptrix-5】靶机
  • 纯电动商用车核心性能评价方法实现
  • uniapp 测试 IPA 包安装到测试 iPhone
  • 如何使用Docker搭建哪吒监控面板程序
  • java2025热点面试题之springmvc
  • C# 类型转换
  • vue3:四嵌套路由的实现
  • 学Java第三十天------------多态
  • 20250226-代码笔记05-class CVRP_Decoder
  • 【无人机】无人机通信模块,无人机图数传模块的介绍,数传,图传,图传数传一体电台,
  • 什么是HA
  • keil主题(vscode风格)
  • ClickHouse
  • P1123 取数游戏
  • 实战案例:排查 Java 应用 CPU 飙高问题
  • 自由学习记录(40)
  • HFSS 仿真学习1 K波段定向耦合器
  • JAVA面试_进阶部分_netty面试题
  • 【Java】多线程篇 —— 多线程的基本使用
  • 58、深度学习-自学之路-自己搭建深度学习框架-19、RNN神经网络梯度消失和爆炸的原因(从公式推导方向来说明),通过RNN的前向传播和反向传播公式来理解。
  • 网站设计技巧/百度搜索引擎优化相关性评价
  • 中小学生做试卷的网站/搜索引擎优化是做什么的
  • 网站开发外包协议/新闻热点大事件
  • fullpage wow做的网站/网络推广协议
  • 上海 餐饮网站建设/最新消息今天的新闻
  • 怎样优化网站排名靠前/2022磁力链接搜索引擎推荐