1. JDBC连接池
1.1 JDBC连接池简介
线程池可以复用一个线程,这样大量的小任务通过线程池的线程执行,就可以避免反复创建线程带来的开销。
同样JDBC可以复用一个JDBC连接
JDBC的连接池可以维护若干个JDBC连接,在执行数据库任务的时候,可以从连接池中直接获取连接,而不是反复创建和关闭JDBC连接
1.2 JDBC连接池接口:
- javax.sql.DataSource
- JDK只提供了连接池的定义,所以我们还要实现JDBC的连接池。常用的开源实现:
* HikariCP
* C3P0
* BoneCP
* Druid
1.3 以HiKariCP为例
导入依赖
<!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>3.3.1</version>
</dependency>
演示代码
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/test");
config.setUsername("root");
config.setPassword("password");
config.addDataSourceProperty("connectionTimeout", "1000"); //连接超时1秒
config.addDataSourceProperty("idleTimeout", "60000"); //空闲连接60秒
config.addDataSourceProperty("maximumPoolSize", "10"); //最大连接数10
DataSource dataSource = new HikariDataSource(config);
package com.feiyangedu.sample.pop3;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class JdbcSelect2 {
static final String JDBC_URL = "jdbc:mysql://localhost:13306/test0828?useSSL=false&characterEncoding=utf-8&serverTimeZone=UTC";
static final String JDBC_USER = "root";
static final String JDBC_PASSWORD = "123456";
public static void main(String[] args) throws Exception{
DataSource dataSource = createDataSource();
List<Thread> threads = new ArrayList<>();
for(int i=1;i<=4;i++){
final int classId=i;
Thread t = new Thread(){
public void run(){
try{
Thread.sleep((long)(Math.random()*1000));
}catch (InterruptedException e){
e.printStackTrace();
}
List<Student> list = getStudentsOfClass(dataSource,classId);
System.out.println("Students of class: "+classId+";");
for(Student student:list){
System.out.println(student);
}
}
};
threads.add(t);
}
for(Thread t:threads){
t.start();
}
for(Thread t:threads){
t.join();
}
}
static DataSource createDataSource(){ //创建一个连接池
HikariConfig config = new HikariConfig();
config.setJdbcUrl(JDBC_URL);
config.setUsername(JDBC_USER);
config.setPassword(JDBC_PASSWORD);
config.addDataSourceProperty("connectionTimeout", "1000"); //连接超时:1秒
config.addDataSourceProperty("idleTimeout", "60000"); //空闲超时:60秒
config.addDataSourceProperty("maximumPoolSize", "10"); //最大连接数:10
return new HikariDataSource(config);
}
static List<Student> getStudentsOfClass(DataSource dataSource,long theclassId){
try(Connection conn = dataSource.getConnection()){ //获取Connection对象
System.err.println("Using connection:"+conn);
try(PreparedStatement ps = conn.prepareStatement("select * from students where class_id=?")){
ps.setObject(1,theclassId);
try(ResultSet rs = ps.executeQuery()){
List<Student> list = new ArrayList<>();
while (rs.next()){
long id = rs.getLong("id");
long classId = rs.getLong("class_id");
String name = rs.getString("name");
String gender = rs.getString("gender");
Student std = new Student(id,classId,name,gender);
list.add(std);
}
return list;
}
}
}catch (SQLException e){
throw new RuntimeException(e);
}
}
}
2. 总结
数据库连接池(javax.sql.DataSource):
- 可以复用Connection,避免反复创建新连接,提高运行效率
- 可以配置连接池的详细参数