一.数据库连接池
1.为什么要有连接池
为什么要有连接池?
由于建立数据库连接是一种非常耗时、耗资源的行为,
所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,使用完毕后再归还到连接池中。
数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏。这项技术能明显提高对数据库操作的性能。
连接池基本的思想是在系统初始化的时候,将数据库连接作为对象存储在内存中,当用户需要访问数据库时,并非建立一个新的连接,而是从连接池中取出一个已建立的空闲连接对象。使用完毕后,用户也并非将连接关闭,而是将连接放回连接池中,以供下一个请求访问使用。而连接的建立、断开都由连接池自身来管理。同时,还可以通过设置连接池的参数来控制连接池中的初始连接数、连接的上下限数以及每个连接的最大使用次数、最大空闲时间等等。也可以通过其自身的管理机制来监视数据库连接的数量、使用情况等
2.分类
常见的数据库连接池有DBCP C3P0 Druid连接池等
二. DBCP连接池
DBCP(DataBase Connection Pool)数据库连接池,
是Java数据库连接池的一种,由Apache开发,通过数据库连接池,
可以让程序自动管理数据库连接的释放和断开
使用步骤:
1.导入jar包(commons-dbcp-1.4.jar和commons-pool-1.5.6.jar),记得还要导入数据库驱动jar包
2.使用api 两种方式
a.硬编码
a.硬编码(不推荐)
//创建连接池
BasicDataSource ds = new BasicDataSource();
//配置信息
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql:///day07");
ds.setUsername("root");
ds.setPassword("1234");
Connection conn=ds.getConnection();
String sql="insert into category values(?,?);";
PreparedStatement st=conn.prepareStatement(sql);
//设置参数
st.setString(1, "c011");
st.setString(2, "饮料");
int i = st.executeUpdate();
System.out.println(i);
*** 采用配置文件的方式
//存放配置文件
Properties prop = new Properties();
prop.load(new FileInputStream("src/dbcp.properties"));
//设置
//prop.setProperty("driverClassName", "com.mysql.jdbc.Driver");
//创建连接池
DataSource ds = new BasicDataSourceFactory().createDataSource(prop);
Connection conn=ds.getConnection();
String sql="insert into category values(?,?);";
PreparedStatement st=conn.prepareStatement(sql);
//设置参数
st.setString(1, "c012");
st.setString(2, "饮料1");
int i = st.executeUpdate();
System.out.println(i);
2. DBCP的两种使用方式
a.硬编码(不推荐)
硬编码方式会将代码写死,不建议使用
package org.westos.demo;
import org.apache.commons.dbcp.BasicDataSource;
import java.sql.Connection;
import java.util.concurrent.ExecutionException;
public class MyTest {
public static void main(String[] args) throws Exception {
//数据库连接池:
//DBCP:1.依赖DBCP的两个jar包 ,别忘了MySQL的驱动jar包
//使用方式:1.硬编码。不够灵活,代码是写死的,不建议使用
BasicDataSource bds = new BasicDataSource();
//设置驱动路径
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setUrl("jdbc:mysql://localhost:3306/mydb2");
bds.setUsername("root");
bds.setPassword("123456");
Connection connection = bds.getConnection();
System.out.println(connection);
/* jdbc:mysql://localhost:3306/mydb2, UserName=root@localhost, MySQL-AB JDBC Driver */
}
}
b.配置文件的方式
从配置文件中读取驱动路径,url,用户名和密码等,配置文件可以更改,建议使用
配置文件,一般放于项目的根目录下
#连接基本设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2
username=root
password=123456
#<!--扩展配置 了解-->
#初始化连接
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=gbk
#指定由连接池所创建的连接的自动提交(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
测试文件,直接从配置文件中取出数据即可
package org.westos.demo;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
public class MyTest2 {
public static void main(String[] args) throws Exception{
//DBCP:配置文件方式
Properties properties = new Properties();
properties.load(new FileInputStream("dbcp.properties"));
DataSource dataSource = BasicDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();
System.out.println(connection);
/*jdbc:mysql://localhost:3306/mydb2, UserName=root@localhost, MySQL-AB JDBC Driver*/
}
}
三.C3P0
C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibernate、Spring等。
c3p0与dbcp区别
dbcp没有自动回收空闲连接的功能
c3p0有自动回收空闲连接功能
使用步骤:
1.导入jar包(c3p0-0.9.1.2.jar)
2.使用api
方式1:硬编码
ComboPooledDataSource ds = new ComboPooledDataSource();
//设置基本参数
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql:///day07");
ds.setUser("root");
ds.setPassword("1234");
Connection conn=ds.getConnection();
String sql="insert into category values(?,?);";
PreparedStatement st=conn.prepareStatement(sql);
//设置参数
st.setString(1, "c013");
st.setString(2, "毒药");
int i = st.executeUpdate();
System.out.println(i);
*** 采用配置文件的方式
b.配置文件
要求1:配置文件的名称:c3p0.properties 或者 c3p0-config.xml
要求2:配置文件的路径:src下
编码只需要一句话
new ComboPooledDataSource()//使用默认的配置
//可以切换xml配置文件中的标签 来加载不同的配置比如更换Orecal的数据库的配置
new ComboPooledDataSource(String configName)//使用命名的配置 若配置的名字找不到,使用默认的配置
a.硬编码方式
package org.westos.demo;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
public class MyTest {
public static void main(String[] args) throws Exception{
//c3p0与dbcp区别
//dbcp没有自动回收空闲连接的功能
//c3p0有自动回收空闲连接功能
//C3P0:依赖C3P0的一个jar包 别忘了数据库的驱动jar包
//硬编码:
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/mydb2");
cpds.setUser("root");
cpds.setPassword("123456");
Connection connection = cpds.getConnection();
System.out.println(connection);
//com.mchange.v2.c3p0.impl.NewProxyConnection@2aae9190
}
}
b.配置文件方式
配置文件的注意事项:
因为要根据配置文件来来创建对象,因此配置文件的路径必须直接在src下,配置文件的名称必须是c3p0.properties 或者 c3p0-config.xml,要更改的话,配置文件中的内容也要更改
测试类:
package org.westos.demo;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
public class MyTest2 {
public static void main(String[] args) throws Exception{
//C3P0:对配置文件有两个要求。
//1.配置文件放在src下。
//2.配置文件名是固定的。就叫做 c3p0.properties
//使用c3p0-config.xml的配置文件,可以根据第二配置的名字来使用第二配置。
ComboPooledDataSource ds = new ComboPooledDataSource("myname");
Connection conn = ds.getConnection();
System.out.println(conn);
/*ComboPooledDataSource ds = new ComboPooledDataSource();
Connection conn = ds.getConnection();
System.out.println(conn);
com.mchange.v2.c3p0.impl.NewProxyConnection@6bc168e5*/
}
}
配置文件: c3p0.properties
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql:///mydb2
c3p0.user=root
c3p0.password=123456
c3p0-config.xml
<c3p0-config>
<!-- 默认配置,如果没有指定则使用这个配置 -->
<default-config>
<!-- 基本配置 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mydb2</property>
<property name="user">root</property>
<property name="password">123456</property>
<!--扩展配置-->
<property name="checkoutTimeout">30000</property>
<property name="idleConnectionTestPeriod">30</property>
<property name="initialPoolSize">10</property>
<property name="maxIdleTime">30</property>
<property name="maxPoolSize">100</property>
<property name="minPoolSize">10</property>
<property name="maxStatements">200</property>
</default-config>
<!--第二配置-->
<!-- 命名的配置 -->
<named-config name="myname">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/myname</property>
<property name="user">root</property>
<property name="password">123456</property>
<!-- 如果池中数据连接不够时一次增长多少个 -->
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">20</property>
<property name="minPoolSize">10</property>
<property name="maxPoolSize">40</property>
<property name="maxStatements">20</property>
<property name="maxStatementsPerConnection">5</property>
</named-config>
</c3p0-config>
四.Druid 阿里德鲁伊连接池
DRUID是阿里巴巴开源平台上一个数据库连接池实现,它结合了C3P0、DBCP、PROXOOL等DB池的优点,同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB连接池(据说是目前最好的连接池,不知道速度有没有BoneCP快)。
使用步骤,导入德鲁伊的jar包
1.采用硬编码的方式
//采用硬编码的方式来创建连接池
DruidDataSource dataSource = new DruidDataSource();
//设置参数
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("123456");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/crm");
dataSource.setInitialSize(5);
dataSource.setMinIdle(1);
dataSource.setMaxActive(10);
//获取连接对象
DruidPooledConnection connection = dataSource.getConnection();
System.out.println(connection);
2.采用配置文件的方式,
a.引入配置文件
b.加载配置文件
//采用加载配置文件的方式
Properties properties = new Properties();
properties.load(new FileInputStream("src/db_server.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection conn = dataSource.getConnection();
System.out.println(conn);
a.硬编码
package org.westos.demo;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
public class MyTest {
public static void main(String[] args) throws Exception{
//德鲁伊连接池
//a.硬编码
DruidDataSource dds = new DruidDataSource();
dds.setDriverClassName("com.mysql.jdbc.Driver");
dds.setUrl("jdbc:mysql://localhost:3306/mydb2");
dds.setUsername("root");
dds.setPassword("123456");
DruidPooledConnection connection = dds.getConnection();
System.out.println(connection);//com.mysql.jdbc.JDBC4Connection@3d82c5f3
}
}
b.配置文件 druid.properties
#\u57FA\u672C\u914D\u7F6E
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb2
username=root
password=123456
#\u9ED8\u8BA4\u914D\u7F6E
filters=stat
initialSize=2
maxActive=300
maxWait=60000
timeBetweenEvictionRunsMillis=60000
minEvictableIdleTimeMillis=300000
validationQuery=SELECT 1
testWhileIdle=true
testOnBorrow=false
testOnReturn=false
poolPreparedStatements=false
maxPoolPreparedStatementPerConnectionSize=200
测试类
package org.westos.demo;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.util.Properties;
public class MyTest2 {
public static void main(String[] args) throws Exception{
//德鲁伊连接池 b.配置文件方式
Properties properties = new Properties();
properties.load(new FileInputStream("src/druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
Connection connection = dataSource.getConnection();
System.out.println(connection);
/*com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@769c9116*/
}
}
五.DBUtils
1.概述
Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,
使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
使用步骤:
1.导入jar包(commons-dbutils-1.4.jar)
2.创建一个queryrunner类
queryrunner作用:操作sql语句
构造方法:
new QueryRunner(Datasource ds);
3.编写sql
4.执行sql
query(..):执行r操作
update(...):执行cud操作
使用步骤
// 创建对象
QueryRunner runner = new QueryRunner(new ComboPooledDataSource());
// 定义sql
String sql = "insert into bank(username,money) values(?,?)";
// 执行sql
runner.update(sql,"赵六",500);
....
执行查询后返回的结果集
ResultSetHandler:封装结果集 接口
BeanListHandler, 将查询结果的每一条记录封装成指定的bean对象,将每一个bean对象放入list中 返回.
创建Bean对象,注意属性的数据类型和名称要与字段名保持一致
package org.westos.demo;
public class Bank {
private int id;
private String name;
private String money;
@Override
public String toString() {
return "Bank{" +
"id=" + id +
", name='" + name + '\'' +
", money='" + money + '\'' +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMoney() {
return money;
}
public void setMoney(String money) {
this.money = money;
}
public Bank(int id, String name, String money) {
this.id = id;
this.name = name;
this.money = money;
}
public Bank() {
}
}
测试类,如使用Druid连接池
package org.westos.demo;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class MyTest3 {
public static void main(String[] args) throws Exception{
/*Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,
使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。 */
Properties properties = new Properties();
//获取数据源
properties.load(new FileInputStream("src/druid.properties"));
DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
//创建一个QueryRunner对象
QueryRunner queryRunner = new QueryRunner(dataSource);
//增
//queryRunner.update("insert into bank values (?, ?, ?)", 3,"李白",2000);
//queryRunner.update("insert into bank values (?, ?, ?)", 4,"杜甫",3000);
//查
/*
//把查询到的每一条结果封装成实体类,再最终把每一个实体类放到list集合中---BeanListHandler是ResultSetHandler接口的实现类
List<Bank> list = queryRunner.query("select * from bank", new BeanListHandler<Bank>(Bank.class));
System.out.println(list);
[Bank{id=1, name='张三时', money='500'}, Bank{id=2, name='李四', money='1500'}, Bank{id=3, name='李白', money='2000'}, Bank{id=4, name='杜甫', money='3000'}]
*/
//只能查到一条数据
Bank bank = queryRunner.query("select * from bank where id>?", new BeanHandler<>(Bank.class), 0);
System.out.println(bank);
/*Bank{id=1, name='张三时', money='500'}*/
//改
queryRunner.update("update bank set name=? where id=?","李白拜拜","3");
Bank bank1 = queryRunner.query("select * from bank where id = ?", new BeanHandler<>(Bank.class), 3);
//把查询到的一条结果封装成实体类
System.out.println(bank1);
/*Bank{id=3, name='李白拜拜', money='2000'}*/
//删
queryRunner.update("delete from bank where id=?",1);
//键为字段名,值为value,然后封装到List集合中(可以不用构建Bean对象)
List<Map<String, Object>> query = queryRunner.query("select * from bank", new MapListHandler());
System.out.println(query);//[{money=1500, name=李四, id=2}, {money=2000, name=李白拜拜, id=3}, {money=3000, name=杜甫, id=4}]
/**/
}
}