数据库连接池
概念
使用基本的Jdbc进行操作时,每次执行Sql时要先申请一个Connection对象,执行完毕后又释放掉,这样很消耗性能。所以使用池化技术,每次访问数据库,从连接池中取出一个Connection对象,访问完毕后,将Connection对象归还给连接池。以达到复用连接对象,降低性能开销的目的。
好处
-
避免频繁的创建和销毁Connection对象,提高性能
-
方便对Connection对象进行统一的管理
实现
- Jdbc标准中定义了一个接口DataSource,这个接口由驱动程序供应商实现,有3种实现
- 基本实现:可生成标准的Connection
- 连接池实现:可生成会自动参与连接池的Connection
- 分布式事务实现:可生成可用于分布式事务的Connection
- 若是通过连接池实现的DataSource,获取到的Connection,进行关闭时,会将Connection归还给连接池,而不是关闭Connection
连接池使用方法
- 创建DataSource对象
- 调用DataSource的
getConnection()
方法获取连接 - 操作完成后,调用Connection的close方法,归还连接(若标准的Connection,调用close方法会关闭连接。通过数据库连接池获取的Connection,调用close方法不会关闭连接,而会归还连接)
具体的连接池技术
c3p0
使用步骤
-
导入jar包
<!-- c3p0 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.5</version> </dependency>
-
创建配置文件:
c3p0默认会查找classpath的顶级目录下的c3p0.properties文件或c3p0-config.xml的文件
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <!-- 可以配置多数据源,默认会加载default-config,也可以通过name来指定 --> <!-- 默认配置 --> <default-config> <!-- 连接四大参数配置 --> <!-- 对mysql8,若不指定serverTimezone,则c3p0会报错 --> <property name="jdbcUrl">jdbc:mysql:///yogurt?userSSL=false&characterEncoding=UTF-8&serverTimezone=UTC&autoReconnect=true</property> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="user">root</property> <property name="password">root</property> <!-- 池参数配置 --> <property name="initialPoolSize">5</property> <property name="maxPoolSize">10</property> <property name="checkoutTimeout">3000</property> </default-config> <!-- 其他库 --> <named-config name="other-config"> <property name="jdbcUrl">jdbc:mysql://localhost:3306/other</property> <property name="driverClass">com.mysql.cj.jdbc.Driver</property> <property name="user">root</property> <property name="password">123</property> <property name="acquireIncrement">3</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">2</property> <property name="maxPoolSize">10</property> </named-config> </c3p0-config>
-
创建核心对象CombPooledDataSource
-
获取连接 getConnection()
代码示例:
@Test public void testC3p0() throws SQLException { //会使用默认配置 DataSource dataSource = new ComboPooledDataSource(); //下面会使用other-config这一项配置 //ComboPooledDataSource dataSource = new ComboPooledDataSource("other-config"); Connection connection = dataSource.getConnection(); Statement statement = connection.createStatement(); ResultSet set = statement.executeQuery("select * from user limit 3"); while (set.next()){ String name = set.getString("name"); System.out.println(name); } statement.close(); connection.close(); } @Test public void testC3p0_2() throws SQLException { DataSource dataSource = new ComboPooledDataSource(); //配置了最大连接数是10 for (int i = 0; i < 12; i++){ Connection connection = dataSource.getConnection(); System.out.println(i + ":" + connection); if (i == 6 || i == 5){ //归还连接 //这样以来在超过10之后的2次也能获取到连接 connection.close(); } } }
druid
使用步骤
-
导入jar包
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.22</version> </dependency>
-
配置文件
druid.properties
文件名任意,可以放在任意目录,因为druid不会像c3p0那样自动加载,druid需要手动加载配置文件
db.url=jdbc:mysql://localhost:3306/yogurt?userSSL=false&characterEncoding=UTF-8&serverTimezone=UTC db.user=root db.password=root db.driverClass=com.mysql.cj.jdbc.Driver
-
获取DataSource时,要通过工厂类DruidDataSourceFactory
-
获取Connection
封装druid,形成一个util,对外提供
- 获取连接方法
- 释放资源方法
- 获取连接池方法
public class DruidUtil {
private static DataSource dataSource;
static {
try {
Properties properties = new Properties();
properties.load(DruidUtil.class.getClassLoader().getResourceAsStream("druid.properties"));
dataSource = DruidDataSourceFactory.createDataSource(properties);
}catch (Exception e){
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
//从连接池取出一个Connection
return dataSource.getConnection();
}
//释放资源
public static void close(Statement statement,Connection connection){
close(null,statement,connection);
}
public static void close(ResultSet resultSet,Statement statement, Connection connection){
if (resultSet != null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement != null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null){
try {
//归还连接
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//返回连接池
public static DataSource getDataSource(){
return dataSource;
}
}
dbcp
略