上一篇:21【JDBC操作数据库元数据】
下一篇:未完待续…
我们使用JDBC操作数据库时,必须首先先建立一个Connection网络连接,使用完毕之后再将这个连接关闭释放对应的资源,连接对象需要不停的创建,不停的关闭。而创建/关闭一个网络连接是非常消耗资源的一个操作,我们希望创建出来的连接使用完毕后不关闭,而是交给某个容器进行管理,等到下次使用的时候再从容器中拿出来;这个容器就是我们所说的连接池!
Tips:连接池的思想和我们之前学习过的线程池的概念是一模一样的,只不过线程池里面存储的都是线程,而连接池里面存储的都是Connection连接;
连接对象的使用问题:
连接池需要解决两个问题
使用连接池的情况:
在JDK中提供有一个连接池的顶层接口,但JDK本身并没有具体实现,由第三方厂商来实现;这里也是采用面向对象来进行解耦操作;
DataSource接口中的方法 | 描述 |
---|---|
Connection getConnection() | 从连接池中得到一个连接对象 |
常用参数 | 描述 |
---|---|
初始连接数 | 连接池创建的时候,一开始在连接池中有多少个连接对象 |
最大连接数 | 连接池中最多可以创建多少个连接对象 |
最长等待时间 | 如果连接池中所有的连接对象都在使用,新来的用户等待多久以后抛出异常。单位毫秒 |
最长空闲回收时间 | 如果某个连接对象长时间没有用户使用,多久以后进行回收。不是所有的连接池都支持。 |
需要注意的是,这些参数并不是JDK中规定的,而是我们认为一个连接池中应该要具备的一些公共参数,而且JDK中并没有对连接池进行实现,连接池具体会有那些参数可以设置这个JDK也并没有进行规范,而是交给其他的第三方厂商来自行决定,我们要根据使用的连接池厂商不同来具体的设置连接池参数;
package com.dfbz.pool;
import javax.sql.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;
/**
* @author lscl
* @version 1.0
* @intro: 这是第三方厂商实现连接池的类
*/
public class MyDataSource implements DataSource {
//创建连接池的几个属性
private int initPoolSize = 5; //初始连接数
private int maxPoolSize = 10; //最大连接数
private int currSize = 0; //当前已经创建了多少个连接对象,计数的作用
//创建一个集合,模拟连接池
private LinkedList<Connection> pool = new LinkedList<>();
//在构造方法中创建好初始的连接数
public MyDataSource() {
for (int i = 0; i < initPoolSize; i++) {
//创建一个连接对象,并且加到池中最后一个
pool.addLast(createConnection());
}
}
//写一个方法创建连接对象
private Connection createConnection() {
try {
//连接数加1
currSize++;
return DriverManager.getConnection("jdbc:mysql:///test?useSSL=true","root","admin");
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 得到一个连接对象
* @return
* @throws SQLException
*/
@Override
public Connection getConnection() throws SQLException {
//如果连接池中有连接对象,直接返回即可
if (pool.size() > 0) {
//从连接池中取一个元素,返回
return pool.removeFirst();
}
//如果连接池中没有对象了,但当前连接数小于最大连接数的
else if (pool.size() == 0 && currSize < maxPoolSize) {
return createConnection(); //再创建一个新的连接对象
}
//如果已经到达最大连接数
else {
throw new SQLException("已经到达最大连接数:" + maxPoolSize);
}
}
/**
* 关闭连接的方法
*/
public void releaseConnection(Connection conn) {
//将连接对象放回到连接池中
pool.addLast(conn);
}
@Override
public Connection getConnection(String username, String password) throws SQLException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
}
package com.dfbz.demo;
import com.dfbz.pool.MyDataSource;
import java.sql.Connection;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo01_MyDataSource {
public static void main(String[] args) throws Exception {
//创建数据源(默认初始化10个连接)
MyDataSource ds = new MyDataSource();
//从数据源中得到10个连接对象
for (int i = 1; i <= 10; i++) {
Connection conn = ds.getConnection();
System.out.println("得到第" + i + "个连接" + conn);
if (i == 5) {
// 放到连接池中
ds.releaseConnection(conn);
}
}
}
}
Druid是阿里巴巴开发的号称为监控而生的数据库连接池,在功能、性能、扩展性方面,都超过其他数据库连接池。Druid已经在阿里巴巴部署了超过600个应用,经过多年生产环境大规模部署的严苛考验。如:一年一度的双十一活动,每年春运的抢火车票。
Druid的下载地址:https://github.com/alibaba/druid
参数 | 说明 |
---|---|
url | 连接字符串 |
username | 用户名 |
password | 密码 |
driverClassName | 驱动库com.mysql.jdbc.Driver |
initialSize | 初始连接数 |
maxActive | 最大连接数 |
maxWait | 最长等待时间 |
DruidDataSourceFactory的方法 | 方法 |
---|---|
public static DataSource createDataSource(Properties properties) | 通过属性对象得到数据源对象 |
在src目录下新建一个Druid配置文件,命名为:druid.properties(文件名不强制)
# 连接字符串
url=jdbc:mysql://localhost:3306/test?useSSL=true
# 用户名
username=root
password=admin
driverClassName=com.mysql.jdbc.Driver
#初始连接数
initialSize=5
#最大连接数
maxActive=10
#最长等待时间
maxWait=2000
package com.dfbz.demo;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo02_DruidDataSource {
public static void main(String[] args) throws Exception {
//创建属性对象
Properties properties = new Properties();
//src就是类路径所在的目录,从类路径下加载属性文件,转成字节输入流
InputStream in
= Demo02_DruidDataSource.class.getClassLoader().getResourceAsStream("druid.properties");
properties.load(in);
// 根据加载到的配置来创建一个数据源
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
// 获取11个连接对象
for (int i = 1; i <= 11; i++) {
Connection conn = dataSource.getConnection();
System.out.println("第" + i + "个连接对象:" + conn);
// 释放一个
if (i == 5) {
conn.close();
}
}
}
}
package com.dfbz.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* @author lscl
* @version 1.0
* @intro: 数据源的工具类
*/
public class DataSourceUtils {
private static DataSource ds;
/**
* 在静态代码块中创建数据源对象
*/
static {
// 创建属性对象
Properties info = new Properties();
try (
// 得到输入流
InputStream in = DataSourceUtils.class.getClassLoader().getResourceAsStream("druid.properties");) {
// 加载到属性对象中
info.load(in);
ds = DruidDataSourceFactory.createDataSource(info);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到数据源
*/
public static DataSource getDataSource() {
return ds;
}
/**
* 从连接池中得到连接对象
*/
public static Connection getConnection() {
try {
return ds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 释放资源
*/
public static void close(Connection conn, Statement stmt, ResultSet rs) {
//关闭结果集
if (rs!=null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//关闭语句对象
if (stmt!=null) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
//关闭连接对象
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 关闭连接
*/
public static void close(Connection conn, Statement stmt) {
close(conn, stmt, null);
}
}
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`birthday` date NULL DEFAULT NULL,
`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of t_user
-- ----------------------------
INSERT INTO `t_user` VALUES (1, 'root', 'admin', '1998-10-10', '江西景德镇');
INSERT INTO `t_user` VALUES (2, 'admin', '123', '1997-08-21', '福建福州');
INSERT INTO `t_user` VALUES (3, '张三', 'admin', '2022-06-03', '江西赣州');
package com.dfbz.demo;
import com.dfbz.utils.DataSourceUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Date;
/**
* @author lscl
* @version 1.0
* @intro:
*/
public class Demo03_DataSourceUtils {
public static void main(String[] args) throws Exception {
//得到连接对象
Connection conn = DataSourceUtils.getConnection();
//得到预编译的语句对象
PreparedStatement ps = conn.prepareStatement("select * from t_user;");
//得到结果集
ResultSet rs = ps.executeQuery();
//封装数据
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("username");
String gender = rs.getString("password");
Date birthday = rs.getDate("birthday");
String address = rs.getString("address");
System.out.println("id: " + id);
System.out.println("name: " + name);
System.out.println("gender: " + gender);
System.out.println("birthday: " + birthday);
System.out.println("address: " + address);
System.out.println("------------------");
}
//关闭连接
DataSourceUtils.close(conn, ps, rs);
}
}
上一篇:21【JDBC操作数据库元数据】
下一篇:未完待续…