数据库连接池的意义:
若每次都在需要使用的时候建立连接,TCP三次握手所需消耗时间长,故可以一直保持一些连接存在,省去每次建立的时间及其他消耗。还可以方便集中管理。
工作原理:
1.连接池的建立:根据配置建立
2.连接池中连接的使用管理
2.连接池的关闭:当程序退出时,关闭所有连接
JDBC
一、工作原理:
1.Class.forName():加载驱动
2.DriverManger获取Connection连接
3.创建Statement获取SQL语句
4.返回ResultSet查询结果
5.释放资源
-Connection.getAutoCommit():获得当前事务的提交方式,默认是true
-Connection.setAutoCommit():设置事务的提交属性,参数是true:自动提交;false:不自动提交,取消自动提交,后续手动提交
-Connection.Commit():提交事务
-Connection.rollback():回滚事务
二、使用实例
2.1配置文件db.propertites
driver = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/数据库名?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=TRUE
user = root
password = root
InitSize = 15
2.2使用
public class JdbcTest {
public static void main(String[] args) {
String userName = "root";
String password = "root";
String url = "jdbc:mysql://192.168.20.81:3306/main_config";
String sql = "select * from linkman";
try {
//1.加载Jdbc 的驱动
Class.forName("com.mysql.jdbc.Driver");
//2.提供jdbc连接的url,创建数据库的连接。
Connection connection = DriverManager.getConnection(url, userName, password);
//3. 创建Statement
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//4.执行sql 语句
ResultSet rs = preparedStatement.executeQuery();
//5.处理结果
while (rs.next()) {
System.out.println("id : " + rs.getInt(1) + " linkman_name : " + rs.getString(2) );
}
//6.使用完连接对象以后,记得关闭流
// 关闭记录集
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 关闭声明
if (preparedStatement != null) {
try {
preparedStatement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 关闭连接对象
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、优缺点
优点:简单直接
缺点:代码重复率高、不易维护、不支持分布式、缓存等
c3p0
一、c3p0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象。
优点:功能简单易用,稳定性好。
缺点:性能差。
二、使用实例
2.1导入依赖
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
2.2配置
<c3p0-config>
<!--
C3P0的缺省(默认)配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
-->
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/student</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<!--
C3P0的命名配置,
如果在代码中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”这样写就表示使用的是name是MySQL的配置信息来创建数据源
-->
<named-config name="MySQL">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/student</property>
<property name="user">root</property>
<property name="password">123456</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
DBCP
一、DBCP是一个依赖Jakarta commons-pool对象池机制的数据库连接池.DBCP可以直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP。
缺点:单线程、没有自动回收空闲连接的功能
二、使用实例:
2.1导入依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.8.0</version>
</dependency>
2.2在类目录下加入dbcp的配置文件:dbcpconfig.properties
#连接设置 报错com.mysql.jdbc.Connection.isValid(I)Z,更新mysql包
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
username=root
password=123456
#初始化连接池大小
jdbcPoolInitSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED
2.3建立工具类
package zdb.jdbc.util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSourceFactory;
public class jdbcUtils_DBCP {
/**
* 在java中,编写数据库连接池需实现java.sql.DataSource接口,每一种数据库连接池都是DataSource接口的实现
* DBCP连接池就是java.sql.DataSource接口的一个具体实现
*/
private static DataSource ds = null;
static {
InputStream in = jdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
try {
prop.load(in);
//创建数据源
ds = BasicDataSourceFactory.createDataSource(prop);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
//释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
public static void release(Connection conn,PreparedStatement ps ,ResultSet rs) {
if (conn!=null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (ps!=null) {
try {
ps.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (rs!=null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
rs = null;
}
}
}
2.4连接测试
PreparedStatement ps = null;
ResultSet rs = null;
Connection conn = null;
try {
//conn = jdbcUtils_DBCP.getConnection();
conn = jdbcUtils_DBCP.getConnection();
String sql = "insert into user(uname) values(?)";
//由于版本兼容问题:必须加上PreparedStatement.RETURN_GENERATED_KEYS
ps = conn.prepareStatement(sql,PreparedStatement.RETURN_GENERATED_KEYS);
ps.setString(1, "lonewolf");
ps.executeUpdate();
//获得主键
rs = ps.getGeneratedKeys();
if (rs.next()) {
System.out.println(rs.getInt(1));
}
} catch (SQLException e) {
// TODO Auto-generated catch blockrs
e.printStackTrace();
}
finally {
jdbcUtils_DBCP.release(conn, ps, rs);
//jdbcUtils_C3P0.release(conn, ps, rs);
}
Druid
一、不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser。支持所有JDBC兼容的数据库,包括Oracle、MySql、Derby、Postgresql、SQL Server、H2等等。
优点:可以监控数据库访问性能、性能好
二、使用实例
2.1导入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
2.2基本配置
#必须配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/sumengnan?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Hongkong
spring.datasource.username=root
spring.datasource.password=root
@重要配置
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters[0]=stat
spring.datasource.filters[1]=wall
spring.datasource.filters[2]=log4j
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.useGlobalDataSourceStat=true
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
2.3创建类
@Configuration
public class DruidConfig {
@ConfigurationProperties(prefix = "spring.datasource")
@Bean
public DataSource druid(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123");
initParams.put("allow","");//默认就是允许所有访问
bean.setInitParameters(initParams);
return bean;
}
//2、配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
HikariCP
HikariCP快的原因:
1.字节码更加精简,所以可以加载更多代码到缓存。
2.实现了一个无锁的集合类型,来减少并发造成的资源竞争。
3.使用了自定义的数组类型,相对与ArrayList极大地提升了性能。
4.针对CPU的时间片算法进行优化,尽可能在一个时间片里面完成各种操作。
二、使用实例
2.1导入依赖
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
</dependency>
2.2基本配置
#必须参数
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.url=jdbc:mysql://localhost:3306/sumengnan?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Hongkong
spring.datasource.username=root
spring.datasource.password=root
#重要参数
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
2.3代码使用
HikariConfig config = new HikariConfig("some/path/hikari.properties");
HikariDataSource ds = new HikariDataSource(config);