学习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://www.mzph.cn/bicheng/50862.shtml

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

相关文章

Windows下Pytorch入门深度学习环境安装与配置(CPU版本)

Windows下Pytorch入门深度学习环境安装与配置&#xff08;CPU版本&#xff09; 一、安装过程中各个软件的作用&#xff08;一&#xff09;Python&#xff08;二&#xff09;库 / 包 / package / library&#xff08;三&#xff09;PyTorch / Tensorflow&#xff08;四&#xff…

Java之开发 系统设计 分布式 高性能 高可用

1、restful api 基于rest构建的api 规范&#xff1a; post delete put get 增删改查路径 接口命名 过滤信息状态码 2、软件开发流程 3、命名规范 类名&#xff1a;大驼峰方法名&#xff1a;小驼峰成员变量、局部变量&#xff1a;小驼峰测试方法名&#xff1a;蛇形命名 下划…

【云原生】Docker搭建知识库文档协作平台Confluence

目录 一、前言 二、企业级知识库文档工具部署形式 2.1 开源工具平台 2.1.1 开源工具优点 2.1.2 开源工具缺点 2.2 私有化部署 2.3 混合部署 三、如何选择合适的知识库平台工具 3.1 明确目标和需求 3.2 选择合适的知识库平台工具 四、Confluence介绍 4.2 confluence特…

平面点云三角化边数与点的关系

欢迎关注更多精彩 关注我&#xff0c;学习常用算法与数据结构&#xff0c;一题多解&#xff0c;降维打击。 点云三角化定义 原文 说人话&#xff1a; 一个二维平面点集P三角化结果是一个满足以下条件的三角形集合&#xff1a; 1 所有三角形的并集刚好是P的凸包。 2 所有三角…

python3GUI--new音乐播放器!By:PyQt5(附下载地址)

文章目录 一&#xff0e;前言二&#xff0e;展示1.启动2.MV推荐3.专辑详情页4.歌手详情页5.搜索结果页6.歌曲播放页7.我喜欢歌曲页8.我喜欢专辑页 三&#xff0e;思路&启发1.布局2.细节3.组件复用4.项目结构5.优化速度1.Nuitka1.显著提高性能&#xff1a;2.减小程序体积&am…

Java集合框架2024最通俗易懂(图片超全)

集合 1.1、定义 集合就是类型统一的数据组合而成的数据结构&#xff0c;该数据结构可以任意的改变长度。 1.3、Set Set数据存储结构&#xff0c;无序&#xff0c;且不可以重复&#xff0c;元素可以为null&#xff0c;但是也只能出现一次&#xff0c;如下图: 1.3.1、HashSe…

[240726] Mistral AI 发布新一代旗舰模型 | Node.js 合并 TypeScript 文件执行提案

目录 Mistral AI 发布新一代旗舰模型&#xff1a;Mistral Large 2Node.js 合并 TypeScript 文件执行提案&#xff1a;--experimental-strip-types Mistral AI 发布新一代旗舰模型&#xff1a;Mistral Large 2 Mistral AI 宣布推出新一代旗舰模型 Mistral Large 2&#xff0c;该…

算法-----递归~~搜索~~回溯(宏观认识)

目录 1.什么是递归 1.1二叉树的遍历 1.2快速排序 1.3归并排序 2.为什么会用到递归 3.如何理解递归 4.如何写好一个递归 5.什么是搜索 5.1深度&#xff08;dfs&#xff09;优先遍历&优先搜索 5.2宽度&#xff08;bfs&#xff09;优先遍历&优先搜索 6.回溯 1.什…

Temu测评自养号如何做?三分钟带你入门!

环境系统 现在市场上很多的系统都是现成的或软件包&#xff0c;没有解决风控的能力&#xff0c;如果有需要建议大家自己学习一套技术&#xff0c;把技术掌握在自己手里&#xff0c;这样不会有依赖性 手机端环境:越狱后的ios指定版本手机可以一键新机的系统(参数调试)独享的家…

【NLP自然语言处理】为什么说BERT是bidirectional

首先&#xff0c;来看一下Transformer架构图&#xff1a; 我们知道&#xff0c;Bert设计时主要采用的是Transformer编码器部分&#xff0c;要论述Bert为啥是双向的&#xff0c;我想从编码器和解码器的注意力机制来阐述。 在看这篇博客前&#xff0c;需要对Transformer有一定的…

[C++] vector入门迭代器失效问题详解

文章目录 vector介绍**vector iterator 的使用** vector迭代器失效问题由扩容或改变数据引起的迭代器失效reserve的实现&#xff08;野指针&#xff09;insert实现&#xff08;迭代器位置意义改变&#xff09;insert修改后失效的迭代器 it迭代器失效 erase后的问题总结&#xf…

MyBatis-Plus的基本使用(一)

目录 前言 特性 MyBatis-Plus入门案例 常用注解 小结 前言 这篇文章主要来学习MyBatis-Plus这个非常强大的框架. 在学习MyBatis-Plus之前,需要有MyBatis的学习基础.因为MyBatis -Plus 是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#x…

【Java Bean 映射器】通过 MapStruct 和 BeanUtils 拷贝对象的区别

目录 &#x1f44b;前言 &#x1f440;一、环境准备 &#x1f331;二、拷贝工具使用 2.1 BeanUtils 使用 2.2 MapStruct 使用 &#x1f49e;️三、对比 &#x1f4eb;四、章末 &#x1f44b;前言 小伙伴们大家好&#xff0c;最近在一些技术文章中看到了开发时经常接触的对…

面向对象·回顾;万类之祖object;抽象类Abstract。

回顾面向对象 类与对象 类--------&#xff08;instance实例化对象&#xff09;-------->对象 类图 调出你public方法–接口 访问控制符 常用private&#xff0c;public。 封装 可见性本类包不同包private✓✕✕不写dafalt(默认)✓✓✕protected✓✓继承✓public✓✓✓…

【计算机网络】RIP路由协议实验

一&#xff1a;实验目的 1&#xff1a;掌握在路由器上配置RIPv2。 二&#xff1a;实验仪器设备及软件 硬件&#xff1a;RCMS交换机、网线、内网网卡接口、Windows 2019操作系统的计算机等。具体为&#xff1a;三层交换机1台、路由器2台。 软件&#xff1a;wireshark软件、记…

01-调试开发k8s

使用 Docker 构建 Kubernete 官方 release 是使用 Docker 容器构建的。要使用 Docker 构建 Kubernetes&#xff0c;请遵循以下说明: Requirements docker Key scripts 以下脚本位于 build/ 目录中。请注意&#xff0c;所有脚本都必须从 Kubernetes 根目录运行 build/run.…

【科研绘图】记录一次论文结果复现

复现原论文中的图片是科研的基本功之一&#xff0c;它不仅验证了研究结果的可靠性&#xff0c;确保了科学工作的准确性和可重复性&#xff0c;还深刻地评估了方法的有效性&#xff0c;体现了对原始研究的尊重和对科学过程的严谨态度。这个过程不仅提高了研究的透明度&#xff0…

记忆注意力用于多模态情感计算!

记忆注意力用于多模态情感计算&#xff01; 目录 情感计算 一、概述 二、研究背景 三、模型结构和代码 六、数据集介绍 七、性能展示 八、复现过程 九、运行过程 模型总结 本文所涉及所有资源均在传知代码平台可获取。 情感计算 近年来&#xff0c;社交媒体的快速扩张推动了用户…

信通院发布!首个大模型混合云标准

近日&#xff0c;中国信通院发布了首个大模型混合云标准&#xff0c;通过定位当前大模型混合云的能力水平&#xff0c;为基于混合云的大模型服务实践提供指引&#xff0c;并明确未来提升方向。同时&#xff0c;中国信通院基于标准展开大模型混合云能力成熟度专项测试&#xff0…

智能家居全在手机端进行控制,未来已来!

未来触手可及&#xff1a;智能家居&#xff0c;手机端的全控时代 艾斯视觉的观点是&#xff1a;在不远的将来&#xff0c;家&#xff0c;这个温馨的港湾&#xff0c;将不再只是我们休憩的场所&#xff0c;而是科技与智慧的结晶。想象一下&#xff0c;只需轻触手机屏幕&#xf…