学习Java的日子 Day56 数据库连接池,Druid连接池

Day56

1.数据库连接池

理解:池就是容器,容器中存放了多个连接对象

使用原因:

1.优化创建和销毁连接的时间(在项目启动时创建连接池,项目销毁时关闭连接池)

2.提高连接对象的复用率

3.有效控制项目中连接的个数(连接对象占内存资源)

数据库连接池负责分配、管理和释放数据库连接对象,它允许应用程序重复使用一个现有的数据库连接,而

不是再重新建立一个

1.1 自定义连接池

自己写的连接池类 FastConnectionPool

public class FastConnectionPool {private String driverClassName;private String url;private String username;private String password;private int maxActive;//存储connection连接对象的资源容器(removeFirst)private LinkedList<Connection> list;//get,set方法(没有list的get、set方法)//初始化listpublic void init() throws SQLException {list = new LinkedList<>();try {Class.forName(driverClassName);//创建连接对象,并添加到连接池容器中for (int i = 0; i < maxActive; i++) {Connection connection = DriverManager.getConnection(url, username, password);list.add(connection);}} catch (ClassNotFoundException e) {throw new RuntimeException(e);}}public Connection getConnection() throws SQLException {if(list == null){init();}Connection connection = null;if(!list.isEmpty()){connection = list.removeFirst();}return connection;}//回收connection对象,使用完了不用close()方法关闭,而是回收到list中继续使用,提高复用率public void recovery(Connection connection){list.add(connection);}}

测试类

public class Test01 {public static void main(String[] args) throws SQLException {//创建数据库连接池FastConnectionPool pool = new FastConnectionPool();//设置参数pool.setDriverClassName("com.mysql.cj.jdbc.Driver");pool.setUrl("jdbc:mysql://localhost:3306/2403javaee?characterEncoding=utf8&serverTimezone=UTC&rewriteBatchedStatements=true");pool.setUsername("root");pool.setPassword("123456");pool.setMaxActive(20);//jdbc的查询代码Connection connection = pool.getConnection();String sql = "select * from student";PreparedStatement statement = connection.prepareStatement(sql);ResultSet resultSet = statement.executeQuery();while(resultSet.next()){int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt("age");float salary = resultSet.getFloat("salary");String course = resultSet.getString("course");System.out.println(id + " -- " + name + " -- " + sex + " -- " + age + " -- " + salary + " -- " + course);}resultSet.close();statement.close();pool.recovery(connection);//回收connection对象}
}

1.2 升级自定义连接池(重点重点关注)

DataSource:连接池各有各的实现方式,所以sun公司定义了一个标准,DataSource

注意:市面上有众多的数据库连接池(Druid、C3P0、DBCP),他们都实现Java提供的DataSource接口(简称数据源)

在这里插入图片描述

使用过程,重点是要实现close方法,连接资源 (connection对象) 怎么关闭:装饰模式来帮忙

装饰设计模式(包装模式):目的:改写已存在的类的某个方法或某些方法

数据库连接的包装类(需要实现很多方法)

定义Connection connection对象

定义LinkedList pool;

通过构造方法对上述两个值进行初始化

重写close方法

Public void close(){

pool.addLast(connection);

}

public class MyConnectionWrapper implements Connection {private Connection connection;private LinkedList<Connection> list;//连接池里的容器public MyConnectionWrapper(Connection connection, LinkedList<Connection> list) {this.connection = connection;this.list = list;}@Overridepublic Statement createStatement() throws SQLException {return connection.createStatement();}@Overridepublic PreparedStatement prepareStatement(String sql) throws SQLException {return connection.prepareStatement(sql);}@Overridepublic CallableStatement prepareCall(String sql) throws SQLException {return connection.prepareCall(sql);}@Overridepublic String nativeSQL(String sql) throws SQLException {return connection.nativeSQL(sql);}@Overridepublic void setAutoCommit(boolean autoCommit) throws SQLException {connection.setAutoCommit(autoCommit);}@Overridepublic boolean getAutoCommit() throws SQLException {return connection.getAutoCommit();}@Overridepublic void commit() throws SQLException {connection.commit();}@Overridepublic void rollback() throws SQLException {connection.rollback();}@Overridepublic void close() throws SQLException {System.out.println("将连接包装类对象回收到连接池里的容器");list.add(this);}@Overridepublic boolean isClosed() throws SQLException {return connection.isClosed();}@Overridepublic DatabaseMetaData getMetaData() throws SQLException {return connection.getMetaData();}@Overridepublic void setReadOnly(boolean readOnly) throws SQLException {connection.setReadOnly(readOnly);}@Overridepublic boolean isReadOnly() throws SQLException {return connection.isReadOnly();}@Overridepublic void setCatalog(String catalog) throws SQLException {connection.setCatalog(catalog);}@Overridepublic String getCatalog() throws SQLException {return connection.getCatalog();}//省略一些方法
}

自定义连接池类,需要实现DataSource接口

public class FastConnectionPool implements DataSource {private String driverClassName;private String url;private String username;private String password;private int maxActive;private LinkedList<Connection> list;//get,set方法(没有list的get、set方法)public void init() throws SQLException {list = new LinkedList<>();try {Class.forName(driverClassName);} catch (ClassNotFoundException e) {throw new RuntimeException(e);}for (int i = 0; i < maxActive; i++) {Connection connection = DriverManager.getConnection(url, username, password);//获取连接的方法需要将原本的connection对象进行包装MyConnectionWrapper connectionWrapper = new MyConnectionWrapper(connection, list);list.add(connectionWrapper);}}@Overridepublic Connection getConnection() throws SQLException {if(list == null){init();}Connection connection = null;if(!list.isEmpty()){connection = list.removeFirst();}return connection;}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return null;}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return null;}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return false;}@Overridepublic PrintWriter getLogWriter() throws SQLException {return null;}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {}@Overridepublic int getLoginTimeout() throws SQLException {return 0;}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return null;}
}

测试类,和上面的一样

public class Test01 {public static void main(String[] args) throws SQLException {//创建连接池对象FastConnectionPool pool = new FastConnectionPool();//设置参数//设置参数pool.setDriverClassName("com.mysql.cj.jdbc.Driver");pool.setUrl("jdbc:mysql://localhost:3306/2403javaee?characterEncoding=utf8&serverTimezone=UTC&rewriteBatchedStatements=true");pool.setUsername("root");pool.setPassword("123456");pool.setMaxActive(20);Connection connection = pool.getConnection();String sql = "select * from student";PreparedStatement statement = connection.prepareStatement(sql);ResultSet resultSet = statement.executeQuery();while(resultSet.next()){int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt("age");float salary = resultSet.getFloat("salary");String course = resultSet.getString("course");System.out.println(id + " -- " + name + " -- " + sex + " -- " + age + " -- " + salary + " -- " + course);}resultSet.close();statement.close();connection.close();}
}

1.3 Druid (德鲁伊) 连接池

通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。
也有一些开源组织提供了数据源的独立实现:

· DBCP 数据库连接池

· C3P0 数据库连接池

· Druid德鲁伊)数据库连接池

注意:市面上有众多的数据库连接池(Druid、C3P0、DBCP),他们都实现Java提供的DataSource接口(简称数据源)

在使用了数据库连接池之后,在项目的实际开发中就不需要编写连接数据库的代码了,直接从数据源获得数据库的连接。

需要导包

在这里插入图片描述

public class Test01 {public static void main(String[] args) throws SQLException {//创建连接池对象DruidDataSource pool = new DruidDataSource();//就只变化了这一句话//设置参数pool.setDriverClassName("com.mysql.cj.jdbc.Driver");pool.setUrl("jdbc:mysql://localhost:3306/2403javaee?characterEncoding=utf8&serverTimezone=UTC&rewriteBatchedStatements=true");pool.setUsername("root");pool.setPassword("123456");pool.setMaxActive(20);Connection connection = pool.getConnection();String sql = "select * from student";PreparedStatement statement = connection.prepareStatement(sql);ResultSet resultSet = statement.executeQuery();while(resultSet.next()){int id = resultSet.getInt("id");String name = resultSet.getString("name");String sex = resultSet.getString("sex");int age = resultSet.getInt("age");float salary = resultSet.getFloat("salary");String course = resultSet.getString("course");System.out.println(id + " -- " + name + " -- " + sex + " -- " + age + " -- " + salary + " -- " + course);}resultSet.close();statement.close();connection.close();}
}

1.4 Druid封装DBUtil

DBConfig.properties

driverClassName=com.mysql.cj.jdbc.Driverurl=jdbc:mysql://localhost:3306/2403javaee?characterEncoding=utf8&serverTimezone=UTC&rewriteBatchedStatements=trueuser
name=root
password=123456
maxActive=20

maxActive=20:最大连接对象个数

数据库工具类,修改DBUtil

package com.qf.utils;public class DBUtil {private static DruidDataSource pool;private static ThreadLocal<Connection> local;static{Properties properties = new Properties();try {properties.load(DBUtil.class.getClassLoader().getResourceAsStream("DBConfig.properties"));} catch (IOException e) {throw new RuntimeException(e);}String driverClassName = properties.getProperty("driverClassName");String url = properties.getProperty("url");String username = properties.getProperty("username");String password = properties.getProperty("password");int maxActive = Integer.parseInt(properties.getProperty("maxActive"));//初始化数据库连接池pool = new DruidDataSource();//设置参数pool.setDriverClassName(driverClassName);pool.setUrl(url);pool.setUsername(username);pool.setPassword(password);pool.setMaxActive(maxActive);local = new ThreadLocal<>();}/*** 获取连接对象*/public static Connection getConnection() throws SQLException {Connection connection = local.get();//获取当前线程的Connection对象if(connection == null){connection = pool.getConnection();//获取数据库连接池里的连接对象local.set(connection);//将Connection对象添加到local中}return connection;}/*** 关闭资源*/public static void close(Connection connection, Statement statement, ResultSet resultSet){if(resultSet != null){try {resultSet.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(statement != null){try {statement.close();} catch (SQLException e) {throw new RuntimeException(e);}}if(connection != null){try {if(connection.getAutoCommit()){connection.close();local.set(null);}} catch (SQLException e) {throw new RuntimeException(e);}}}/*** 开启事务*/public static void startTransaction() throws SQLException {Connection connection = getConnection();connection.setAutoCommit(false);}/*** 提交事务*/public static void commit() throws SQLException {Connection connection = local.get();if(connection != null){connection.commit();connection.close();local.set(null);}}public static void rollback() throws SQLException {Connection connection = local.get();if(connection != null){connection.rollback();connection.close();local.set(null);}}/*** 更新数据(添加、删除、修改)*/public static int commonUpdate(String sql,Object... params) throws SQLException {Connection connection = null;PreparedStatement statement = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);int num = statement.executeUpdate();return num;}finally {close(connection,statement,null);}}/*** 添加数据 - 主键回填(主键是int类型可以返回)*/public static int commonInsert(String sql,Object... params) throws SQLException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);paramHandler(statement,params);statement.executeUpdate();resultSet = statement.getGeneratedKeys();int primaryKey = 0;if(resultSet.next()){primaryKey = resultSet.getInt(1);}return primaryKey;}finally {close(connection,statement,resultSet);}}/*** 查询多个数据*/public static <T> List<T> commonQueryList(Class<T> clazz,String sql, Object... params) throws SQLException, InstantiationException, IllegalAccessException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);resultSet = statement.executeQuery();//获取表数据对象ResultSetMetaData metaData = resultSet.getMetaData();//获取字段个数int count = metaData.getColumnCount();List<T> list = new ArrayList<>();while(resultSet.next()){T t = clazz.newInstance();//获取字段名及数据for (int i = 1; i <= count; i++) {String fieldName = metaData.getColumnName(i);Object fieldVal = resultSet.getObject(fieldName);setField(t,fieldName,fieldVal);}list.add(t);}return list;} finally {DBUtil.close(connection,statement,resultSet);}}/*** 查询单个数据*/public static <T> T commonQueryObj(Class<T> clazz,String sql, Object... params) throws SQLException, InstantiationException, IllegalAccessException {Connection connection = null;PreparedStatement statement = null;ResultSet resultSet = null;try {connection = getConnection();statement = connection.prepareStatement(sql);paramHandler(statement,params);resultSet = statement.executeQuery();//获取表数据对象ResultSetMetaData metaData = resultSet.getMetaData();//获取字段个数int count = metaData.getColumnCount();if(resultSet.next()){T t = clazz.newInstance();//获取字段名及数据for (int i = 1; i <= count; i++) {String fieldName = metaData.getColumnName(i);Object fieldVal = resultSet.getObject(fieldName);setField(t,fieldName,fieldVal);}return t;}} finally {DBUtil.close(connection,statement,resultSet);}return null;}/*** 处理statement对象参数数据的处理器*/private static void paramHandler(PreparedStatement statement,Object... params) throws SQLException {for (int i = 0; i < params.length; i++) {statement.setObject(i+1,params[i]);}}/*** 获取当前类及其父类的属性对象* @param clazz class对象* @param name 属性名* @return 属性对象*/private static Field getField(Class<?> clazz,String name){for(Class<?> c = clazz;c != null;c = c.getSuperclass()){try {Field field = c.getDeclaredField(name);return field;} catch (NoSuchFieldException e) {} catch (SecurityException e) {}}return null;}/*** 设置对象中的属性* @param obj 对象* @param name 属性名* @param value 属性值*/private static void setField(Object obj,String name,Object value){Field field = getField(obj.getClass(), name);if(field != null){field.setAccessible(true);try {field.set(obj, value);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
}

封装学生类

public class Student {private int id;private String name;private String sex;private int age;private float salary;private String course;//无参构造,有参构造,get,set,toString方法省略
}

测试类

public class Test01 {public static void main(String[] args) throws SQLException, InstantiationException, IllegalAccessException {String sql = "select * from student";List<Student> students = DBUtil.commonQueryList(Student.class, sql);//打印集合for (Student stu : students) {System.out.println(stu);}}
}

在这里插入图片描述

总结

1.连接池

​ 概念

​ 自定义连接池(两个版本,重点关注第二个版本)

​ Druid连接池

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

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

相关文章

C++初阶学习第四弹——类与对象(中)

目录 一. 类的默认成员函数 二.六种默认成员函数 1、构造函数 1.1 构造函数的作用 1.2 特性 1.3 默认构造函数 2、析构函数 2.1 析构函数的作用 2.2 析构函数的用法 3、拷贝构造函数 3.1 拷贝构造函数的作用 3.2 特征 3.3 默认拷贝构造函数 三.总结 类与对象&…

Selenium 的使用

selenium 是一个自动化测试工具&#xff0c;利用它可以驱动浏览器完成特定的操作&#xff0c;例如点击&#xff0c;下拉等&#xff0c;还可以获取浏览器当前呈现的页面的源代码&#xff0c;做到所见即所爬&#xff0c;对于一些 JavaScript 动态渲染的界面来说&#xff0c;这种爬…

php+bootstrap 编写简易的步骤进度条

个人笔记记录&#xff0c;步骤进度条。 版本一&#xff1a; 初始版本&#xff0c; 当前版本单纯的根据bootstrapCSS进行完成的简易版本。这个比较简单 样式我放在了最底下。 <div class"form-group steps"><div class"steps-height"><di…

ScriptableObject使用

资料 Scripting/Create modular game architecture in Unity with ScriptableObjects 脚本文档 基础 SO是一个Unity对象&#xff0c;继承UnityEngine.Objec&#xff0c; SO最大的特点是实例文件可共享&#xff0c;有点类似静态数据&#xff0c;同一个实例文件可被多个对象引…

【vim】ubuntu20-server 安装配置 vim 最新最详细

在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。【vim】ubuntu20-server 安装配置 vim 最新最详细 开发环境一、vim github二、安装必…

Linux系统下非root用户自行安装的命令切换为root权限时无法使用,提示comman not found解决办法

今天在开发的时候遇上了一个问题就是要去我们数据平台中进行数据的提取&#xff0c;数据存储用的是minio&#xff0c;一个MinIO部署由一组存储和计算资源组成&#xff0c;运行一个或多个 minio server 节点&#xff0c;共同作为单个对象存储库。独立的MinIO实例由具有单个 mini…

快速入门C#设计模式【2】结构型模式

结构型模式 适配器模式 (Adapter)桥接模式 (Bridge)组合模式 (Composite)装饰模式 (Decorator)外观模式 (Facade)享元模式 (Flyweight)代理模式 (Proxy) 适配器模式&#xff08;Adapter Pattern&#xff09; 适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计…

Stable Diffusion 使用详解(3)---- ControlNet

背景 炼丹师在AI绘画的过程中&#xff0c;由于Stable Diffusion的原理是水滴式的扩散作图原理&#xff0c;其实在前面也有提到&#xff0c;他的发挥是‘不稳定’的&#xff0c;因为你没有办法做到精确控制&#xff0c;只能说是大致符合你的预期。你不能总依赖抽卡固定随机数种…

后端采用SpringBoot框架开发的:ADR药物不良反应智能监测系统源码,用于监测和收集药品在使用过程中发生的不良反应的系统

ADR药物不良反应智能监测系统是一套用于监测和收集药品在使用过程中发生的不良反应&#xff08;Adverse Drug Reaction, ADR&#xff09;的系统。该系统基于医院临床数据中心&#xff0c;运用信息技术实现药品不良反应的智能监测、报告管理、知识库查询、统计分析等功能&#x…

昇思25天学习打卡营第22天|CV-Vision Transformer图像分类

打卡 目录 打卡 ViT简介 模型结构 基于ViT实现ImageNet分类任务 环境准备与数据读取 模型解析 Transformer基本原理 Self-Attention模块 代码实现 Transformer Encoder 代码实现 ViT模型的输入 Patch Embedding代码处理输入 整体构建ViT 模型训练与推理 模型训…

通过ATS软件抓取ios手机日志方法记录

1.ios手机下载描述符文件&#xff0c;用于过检测 下载网址&#xff1a;https://developer.apple.com/bug-reporting/profiles-and-logs/?nameB 点击这个下载&#xff0c;之后在手机通用-VPN与设备管理里面找到刚才下载的描述文件然后安装&#xff1b; 2024.6月后注意会提示描…

能链智电的危与机:持续亏损、股价崩塌,CEO王阳如何寻求出路?

近日&#xff0c;能链智电&#xff08;NASDAQ&#xff1a;NAAS&#xff09;发布未经审计的2024年二季度及上半年财报。数据显示&#xff0c;该公司上半年营收增速稳健&#xff0c;核心充电服务的规模效应得到释放。 能链智电在财报中透露&#xff0c;该公司于6月首度实现了单月…

echarts使用案例

1.配置legend icon 根据点击事件动态更换样式 <template><div ref"chart" style"width: 600px; height: 400px;"></div></template><script>import * as echarts from echarts;export default {name: EchartsExample,data(…

图论理论基础

图论理论基础 | 代码随想录 图的基本概念 二维坐标中&#xff0c;多个点连成的线就构成了图。图也可以是一个节点&#xff0c;甚至没有节点&#xff08;空图&#xff09;。 图的种类 整体上一般分为有向图和无向图。 有向图是指图中边是有方向的&#xff0c;无向图是指图中…

《GPT-4o mini:开启开发与创新的新纪元》

在科技发展的快速进程中&#xff0c;OpenAI 推出的 GPT-4o mini 模型如同一阵春风&#xff0c;给开发者们带来了新的希望和机遇。它以其卓越的性能和极具吸引力的价格&#xff0c;成为了行业内热议的焦点。 当我首次听闻 GPT-4o mini 的消息时&#xff0c;内心充满了好奇与期待…

Pytorch笔记1

建议点赞收藏关注&#xff01;持续更新至pytorch大部分内容更完。 整体框架如下 目录 gpu加速数据数据结构张量TensorVariable 预处理数据增强 模型构建模块组织复杂网络初始化网络参数定义网络层 损失函数创建损失函数设置损失函数超参数选择损失函数 优化器管理模型参数管理…

【ESP32 IDF 软件模拟SPI驱动 W25Q64存储与读取数组】

目录 SPISPI介绍SPI时序代码编写&#xff08;spi&w25q64&#xff09; 代码调试 SPI SPI介绍 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;是一种高速、全双工、同步的串行通信总线&#xff0c;常用于微控制器与各种外围设备&…

【React】详解如何获取 DOM 元素

文章目录 一、基础概念1. 什么是DOM&#xff1f;2. 为什么需要获取DOM&#xff1f; 二、使用 ref 获取DOM元素1. 基本概念2. 类组件中的 ref3. 函数组件中的 ref 三、 ref 的进阶用法1. 动态设置 ref2. ref 与函数组件的结合 四、处理特殊情况1. 多个 ref 的处理2. ref 与条件渲…

大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…