Druid连接池实现自定义场景的多数据库的连接
前言
最近在做一个报表的集成maven插件,里面的一个环节需要对多数据源进行维护,基础版直接使用最传统的方式【获取连接=》查询数据=》释放连接】但是这种方式每次的开销实在是太耗时间了,那这时候有两个方案一个是自己去手写一个数据库的连接池,还一个方案就是使用druid来做多数据源的连接池,这道题目还需要选择吗,别人都造好了16缸使用稳定版的发动机给你了,你还自己去造发动机吗,当然是直接使用druid来实现我们的多数据源的连接了。【自己手写下数据库连接池是没什么问题的,知道里面的原理就好了,就不用去重复造发动机了】
DruidDataSource数据源实体
package com.lazyboyl.dynamic.report.core.entity;
import java.util.Date;
/**
* 类描述:数据源的实体类
*
* @author linzef
* @since 2020-04-28
*/
public class DruidDataSource {
/**
* 数据源流水ID
*/
private String druidDataSource Id;
/**
* 数据源名称
*/
private String dataSourceName;
/**
* 驱动名称
*/
private String driverClassName;
/**
* 账号
*/
private String userName;
/**
* 密码
*/
private String userPassword;
/**
* 数据库地址
*/
private String url;
/**
* 1:正常;2:连接失败
*/
private String state;
/**
* 创建时间
*/
private Date crtDate;
/**
* 获取数据源流水ID
*
* @return reportDataSourceId - 数据源流水ID
*/
public String getDruidDataSourceId () {
return druidDataSource Id;
}
/**
* 设置数据源流水ID
*
* @param reportDataSourceId 数据源流水ID
*/
public void setDruidDataSourceId(String druidDataSource ) {
this.druidDataSource = druidDataSource ;
}
/**
* 获取数据源名称
*
* @return dataSourceName - 数据源名称
*/
public String getDataSourceName() {
return dataSourceName;
}
/**
* 设置数据源名称
*
* @param dataSourceName 数据源名称
*/
public void setDataSourceName(String dataSourceName) {
this.dataSourceName = dataSourceName;
}
/**
* 获取驱动名称
*
* @return driverClassName - 驱动名称
*/
public String getDriverClassName() {
return driverClassName;
}
/**
* 设置驱动名称
*
* @param driverClassName 驱动名称
*/
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
/**
* 获取账号
*
* @return userName - 账号
*/
public String getUserName() {
return userName;
}
/**
* 设置账号
*
* @param userName 账号
*/
public void setUserName(String userName) {
this.userName = userName;
}
/**
* 获取密码
*
* @return userPassword - 密码
*/
public String getUserPassword() {
return userPassword;
}
/**
* 设置密码
*
* @param userPassword 密码
*/
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
/**
* 获取数据库地址
*
* @return url - 数据库地址
*/
public String getUrl() {
return url;
}
/**
* 设置数据库地址
*
* @param url 数据库地址
*/
public void setUrl(String url) {
this.url = url;
}
/**
* 获取1:正常;2:连接失败
*
* @return state - 1:正常;2:连接失败
*/
public String getState() {
return state;
}
/**
* 设置1:正常;2:连接失败
*
* @param state 1:正常;2:连接失败
*/
public void setState(String state) {
this.state = state;
}
/**
* 获取创建时间
*
* @return crtDate - 创建时间
*/
public Date getCrtDate() {
return crtDate;
}
/**
* 设置创建时间
*
* @param crtDate 创建时间
*/
public void setCrtDate(Date crtDate) {
this.crtDate = crtDate;
}
}
DruidUtil工具类编写
首先我们创建一个DruidUtil工具类,里面首先初始化一个Map用于存放我们不同的数据源。
/**
* 多数据源的Map的存储对象
*/
public static Map<String, DruidDataSource> map = new HashMap<>();
接着我们编写实现数据库初始化的方法
/**
* 功能描述: 初始化数据库连接池
*
* @param reportDataSource 待初始化的数据库信息
*/
public static void initDataSource(DruidDataSource druidDataSource) {
Properties prop = new Properties();
prop.setProperty("driver", druidDataSource.getDriverClassName());
prop.setProperty("url", druidDataSource.getUrl());
prop.setProperty("connectionProperties", "useUnicode=true;characterEncoding=UTF8");
prop.setProperty("username", druidDataSource.getUserName());
prop.setProperty("password", druidDataSource.getUserPassword());
// 设置数据连接池初始化连接池数量
prop.setProperty("initialSize", "3");
// 最大连接数
prop.setProperty("maxActive", "20");
prop.setProperty("minIdle", "3");
// 连接最大等待时间60秒
prop.setProperty("maxWait", "60000");
prop.setProperty("filters", "stat");
prop.setProperty("timeBetweenEvictionRunsMillis", "35000");
prop.setProperty("minEvictableIdleTimeMillis", "30000");
prop.setProperty("testWhileIdle", "true");
prop.setProperty("testOnBorrow", "false");
prop.setProperty("testOnReturn", "false");
prop.setProperty("poolPreparedStatements", "false");
prop.setProperty("maxPoolPreparedStatementPerConnectionSize", "200");
prop.setProperty("removeAbandoned", "true");
try {
DruidDataSource druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(prop);
map.put(druidDataSource.getDruidDataSourceId(), druidDataSource);
} catch (Exception e) {
e.printStackTrace();
System.out.println("初始化创建连接池失败!");
}
}
最后编写获取我们的数据库连接对象的方法
/**
* 功能描述: 获取数据库的连接
*
* @param id 数据源流水ID
* @return 获取数据库连接
* @throws SQLException
*/
public static DruidPooledConnection getConnection(String id) throws SQLException {
DruidDataSource source = map.get(id);
System.out.println("当前数据库连接池的量为:" + source.getActiveCount() + "---" + source.getActivePeak());
return (DruidPooledConnection) source.getPooledConnection();
}
验证我们的多数据源连接
我们直接在我们的DruidUtil中编写一个main方法然后我们启动20个线程来模拟数据库的访问。
public static void main(String[] args) throws SQLException {
List<ReportDataSource> reportDataSourceList = new ArrayList<>();
ReportDataSource report = new ReportDataSource();
report.setUserName("数据库1账号");
report.setUserPassword("数据库1密码");
report.setUrl("jdbc:mysql://xx:3306/xx?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai");
report.setDriverClassName("com.mysql.jdbc.Driver");
report.setReportDataSourceId("2");
reportDataSourceList.add(report);
report = new ReportDataSource();
report.setUserName("数据库2账号");
report.setUserPassword("数据库2密码");
report.setUrl("jdbc:mysql://xxx:3306/xx?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai");
report.setDriverClassName("com.mysql.jdbc.Driver");
report.setReportDataSourceId("1");
reportDataSourceList.add(report);
// 初始化多个数据源
for (ReportDataSource reportDataSource : reportDataSourceList) {
initDataSource(reportDataSource);
}
// 启动十个线程模拟访问数据库
for(int k=0;k<10;k++){
new Thread(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 1000; j++) {
try {
DruidPooledConnection conn = getConnection("1");
PreparedStatement ps = conn.prepareStatement("select * from xxx");
ResultSet rs = ps.executeQuery();
ResultSetMetaData resultSetMetaData = rs.getMetaData();
// while (rs.next()) {
// for (int i = 0; i < resultSetMetaData.getColumnCount(); i++) {
// System.out.println("==>" + rs.getString(resultSetMetaData.getColumnLabel(i + 1)));
// }
// }
rs.close();
ps.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
这时候我们可以启动我们的main方法,大家会看到我们的控制台会打印如下的信息:
到此处我们就完成了我们的多数据源的druid的实现,我们就可以拿着我们的connection去做任何我们想做的事情了。