Connection getConnection()
Connection getConnection(String username, String password)
1.
2.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
参数 |
描述 |
username |
传递给JDBC驱动的用于建立连接的用户名 |
password |
传递给JDBC驱动的用于建立连接的密码 |
url |
传递给JDBC驱动的用于建立连接的URL |
driverClassName |
使用的JDBC驱动的完整有效的java 类名 |
connectionProperties |
当建立新连接时被发送给JDBC驱动的连接参数, |
注意: 1格式为[propertyName=property;] 可理解为键值对 2. 参数user/password将被明确传递,所以不需要包括在这里。 |
参数 默认值 描述
defaultAutoCommit true 连接池创建的连接的默认的auto-commit状态
defaultReadOnly driver default 连接池创建的连接的默认的read-only状态.
如果没有设置则setReadOnly方法将不会被调用. (某些驱动不支持只读模式,比如:Informix)
defaultTransactionIsolation driver default 连接池创建的连接的默认的TransactionIsolation状态.
下面列表当中的某一个: (参考javadoc)
* NONE
* READ_COMMITTED
* READ_UNCOMMITTED
* REPEATABLE_READ
* SERIALIZABLE
defaultCatalog 连接池创建的连接的默认的catalog
参数 默认值 描述
initialSize 0 初始化连接:连接池启动时创建的初始化连接数量,1.2版本后支持
maxActive 8 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量,
如果设置为非正数则表示不限制
maxIdle 8 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,
如果设置为负数表示不限制
minIdle 0 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,
如果设置为0则不创建
maxWait 无限 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),
超过时间则抛出异常,如果设置为-1表示无限等待
参数 默认值 描述
validationQuery SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,
则查询必须是一个SQL SELECT并且必须返回至少一行记录
testOnBorrow true 指明是否在从池中取出连接前进行检验,如果检验失败,
则从池中去除连接并尝试取出另一个.
注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
testOnReturn false 指明是否在归还到池中前进行检验
注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
testWhileIdle false 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,
则连接将被从池中去除.
注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
timeBetweenEvictionRunsMillis -1 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位.
如果设置为非正数,则不运行空闲连接回收器线程
numTestsPerEvictionRun 3 在每次空闲连接回收器线程(如果有)运行时检查的连接数量
minEvictableIdleTimeMillis 1000 * 60 * 30 连接在池中保持空闲而不被空闲连接回收器线程
(如果有)回收的最小时间值,单位毫秒
参数 默认值 描述
poolPreparedStatements false 开启池的prepared statement 池功能
maxOpenPreparedStatements 不限制 statement池能够同时分配的打开的statements的最大数量,
如果设置为0表示不限制
这里可以开启PreparedStatements池. 当开启时, 将为每个连接创建一个statement池,
并且被下面方法创建的PreparedStatements将被缓存起来:
* public PreparedStatement prepareStatement(String sql)
* public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
注意: 确认连接还有剩余资源可以留给其他statement
参数 默认值 描述
accessToUnderlyingConnectionAllowed false 控制PoolGuard是否容许获取底层连接
如果容许则可以使用下面的方式来获取底层连接:
Connection conn = ds.getConnection();
Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();
...
conn.close();
默认false不开启, 这是一个有潜在危险的功能, 不适当的编码会造成伤害.
(关闭底层连接或者在守护连接已经关闭的情况下继续使用它).请谨慎使用,
并且仅当需要直接访问驱动的特定功能时使用.
注意: 不要关闭底层连接, 只能关闭前面的那个.
参数 默认值 描述
removeAbandoned false 标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制.
如果设置为true, 连接被认为是被泄露并且可以被删除,如果空闲时间超过removeAbandonedTimeout.
设置为true可以为写法糟糕的没有关闭连接的程序修复数据库连接.
removeAbandonedTimeout 300 泄露的连接可以被删除的超时值, 单位秒
logAbandoned false 标记当Statement或连接被泄露时是否打印程序的stack traces日志。
被泄露的Statements和连接的日志添加在每个连接打开或者生成新的Statement,
因为需要生成stack trace。
如果开启"removeAbandoned",那么连接在被认为泄露时可能被池回收. 这个机制在(getNumIdle() < 2)
and (getNumActive() > getMaxActive() - 3)时被触发.
举例当maxActive=20, 活动连接为18,空闲连接为1时可以触发"removeAbandoned".
但是活动连接只有在没有被使用的时间超过"removeAbandonedTimeout"时才被删除,默认300秒.
在resultset中游历不被计算为被使用.
3
30
1000
false
Test
false
100
null
false
60
3
60
15
100
3
root
password
select id from test where id=1
300
false
true
root
false
con_test
30000
30
10
30
25
10
0
200
300
都是开源的连接池
CREATE DATABASE Admin DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci /*建库*/
USE admin /*使用此库*/
CREATE TABLE admin( /*建表*/
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(12) NOT NULL,
pwd VARCHAR(12) NOT NULL
)
/*测试数据*/
INSERT INTO admin(username,pwd) VALUES('王五','1234');
INSERT INTO admin(username,pwd) VALUES('张三','1234');
INSERT INTO admin(username,pwd) VALUES('李四','1234');
package work.itcase.entity;
public class Admin {
private int id;
private String userName;
private String pwd;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public Admin(int id, String userName,String pwd){
super();
this.id = id;
this.userName = userName;
this.pwd = pwd;
}
public Admin(){
}
@Override
public String toString() {
return "Admin [id=" + id + ", userName=" + userName + ", pwd=" + pwd
+ "]";
}
}
package work.itcase.entity;
import java.sql.Connection;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
import work.itcase.utils.JdbcUtil;
public class Apptest {
// 一. 使用Dbutils组件更新
private Connection con = null;
@Test
public void deletetest() throws Exception {
// 0.需要操作的sql
String sql = "delete from admin where id = 2 ";
// 1.创建连接
con = JdbcUtil.getConnection();
// 1.2创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3更新
qr.update(con, sql);
con.close();
}
// 二、使用Dbutils组件添加
@Test
public void inserttest() throws Exception {
// 0.需要操作的sql
// String sql = "insert into admin values(?,?,?)";
String sql = "insert into admin values(2,'张平','0000');";
// 1.创建连接
con = JdbcUtil.getConnection();
// 1.2创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3更新
qr.update(con, sql);
// qr.update(sql,admin.getId(),admin.getUserName(),admin.getPwd());
con.close();
}
// 三、使用Dbutils组件修改
@Test
public void testUpdate() throws Exception {
// 0.需要操作的sql
String sql = "update admin set userName = '赵七',pwd = '0000' where id =3";
// String sql = "update set userName =?,pwd = ? where id =?";
// 1.创建连接
con = JdbcUtil.getConnection();
// 1.2创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3更新
// qr.update(sql,admin.getId(),admin.getUserName(),admin.getPwd());
qr.update(con, sql);
con.close();
}
// 四.使用Dbutils组件查询
@Test
public void testQuery() throws Exception {
String sql = "select * from admin";
// 1.1 连接
Connection con = JdbcUtil.getConnection();
// 1.2 创建核心工具类
QueryRunner qr = new QueryRunner();
// 1.3 查询
List list = qr.query(con, sql, new BeanListHandler(
Admin.class));
/*
* qr.query(参数一,参数二,参数三) 参数三:需实现的接口 可以是自定义的接口 也可以是默认接口 常用的默认接口:
* 1.BeanHandler: 查询返回单个对象 2.BeanListHandler: 查询返回list集合,集合元素是指定的对象
* 3.ArrayHandler, 查询返回结果记录的第一行,封装对对象数组, 即返回:Object[]
* 4.ArrayListHandler, 把查询的每一行都封装为对象数组,再添加到list集合中
* 5.ScalarHandler查询返回结果记录的第一行的第一列 (在聚合函数统计的时候用)
* 6. MapHandler 查询返回结果的第一条记录封装为map
*/
System.out.println(list);
con.close();
}
}
package work.itcase.pool;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.LinkedList;
/**
* 自定义连接池类
* 作用:自定义连接池,管理连接
* @author Administrator
*
*/
public class MyPool {
private int initCount = 3; // 初始化连接数目
private int maxCount = 6; // 最大连接数
private int currentCount = 0; // 记录当前使用的连接数
// 1.连接池(存放所有的初始化连接)
private LinkedList pool = new LinkedList();
// 构造函数(初始化成员变量)初始化连接放入连接池
public MyPool() {
// 初始化连接
for (int i = 0; i < initCount; i++) {
// 记录当前连接数目
currentCount++;
// 创建原始的链接对象
Connection conn = createConnection();
// 把连接加入连接池中
pool.addLast(conn);
}
}
// 2.创建一个新的连接的方法
private Connection createConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
// 原始的目标对象
final Connection conn = DriverManager.getConnection(
"jdbc:mysql:///admin", "root", "0000");
/* ####使用动态代理技术构建连接池中的connection
####*/
Connection proxy = (Connection) Proxy.newProxyInstance(conn
.getClass().getClassLoader(),
new Class[] { Connection.class }, new InvocationHandler() {
// 重写invocatinHadler alt +shift +s
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
// 方法返回值
Object result = null;
// 当前执行的方法的方法名
String methodName = method.getName();
// 判断当前执行close方法的时候,把连接放入连接池
if ("close".equals(methodName)) {
System.out.println("begin:当前执行了close方法开始!");
// 连接放入连接池判断
pool.addLast(conn);
System.out.println("end:当前执行close方法结束!");
} else {
// 调用目标对象方法
result = method.invoke(conn, args);
}
return result;
}
});
return proxy;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
// 3.获取连接池
public Connection getConnection() {
// 3.1 判断连接池中是否有连接, 如果有连接,就直接从连接池取出
if (pool.size() > 0) {
return pool.removeFirst();
}
// 3.2 连接池中没有连接: 判断,如果没有达到最大连接数,创建;
if (currentCount < maxCount) {
// 记录当前使用的连接数
currentCount++;
// 创建连接
return createConnection();
}
// 3.3 如果当前已经达到最大连接数,抛出异常
throw new RuntimeException("当前连接数已经达到上限!");
}
// 4.释放连接
public void realeaseConneciton(Connection conn) {
// 4.1 判断: 池的数目如果小于初始化连接,就放入池中
if (pool.size() < initCount) {
pool.addLast(conn);
} else {
// 4.2关闭
currentCount--;
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
public static void main(String args[]) throws SQLException {
MyPool pool = new MyPool();
System.out.println("当前连接:" + pool.currentCount);
// 使用连接
pool.getConnection();
pool.getConnection();
Connection conn4 = pool.getConnection();
Connection conn3 = pool.getConnection();
Connection conn2 = pool.getConnection();
Connection conn1 = pool.getConnection();
conn1.close();
// 再获取
pool.getConnection();
System.out.println("连接池:" + pool.pool.size()); // 0
System.out.println("当前连接: " + pool.currentCount); // 3
}
}
自定义连接池的步骤总结
1.自定义连接池类MyPool
2.指定全局参数 初始化数目、最大连接数、当前连接、 连接池集合
3.构造函数:循环创建3个连接
4.创建一个连接的方法
4.1建立数据库原始连接
4.2使用动态代理技术构建连接池中的connection
4.2.1重写invocatinHadler alt +shift +s
4.2.1.1定义当前执行的方法的方法名
4.2.1.2判断当前执行close方法的时候,把连接放入连接池
4.2.1.3连接放入连接池判断
4.2.1.4调用目标对象方法
5.获取连接
5.1判断连接池中是否有连接, 如果有连接,就直接从连接池取出
5.2连接池中没有连接: 判断,如果没有达到最大连接数,创建;
5.3如果当前已经达到最大连接数,抛出异常
6.释放连接
6.1判断: 池的数目如果小于初始化连接,就放入池中
6.2关闭资源
package work.itcase.dbcp;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.junit.Test;
public class DBCPtest {
// 1. 硬编码方式实现连接池
@Test
public void testDbcp() throws Exception {
// DBCP连接池核心类
BasicDataSource dataSouce = new BasicDataSource();
// 连接池参数配置:初始化连接数、最大连接数 / 连接字符串、驱动、用户、密码
dataSouce.setUrl("jdbc:mysql:///admin?characterEncoding=utf8"); //数据库连接字符串
dataSouce.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动
dataSouce.setUsername("root"); //数据库连接用户
dataSouce.setPassword("0000"); //数据库连接密码
dataSouce.setInitialSize(3); // 初始化连接
dataSouce.setMaxActive(6); // 最大连接
dataSouce.setMaxIdle(3000); // 最大空闲时间
// 获取连接
Connection conn = dataSouce.getConnection();
conn.prepareStatement("delete from admin where id=3").executeUpdate();
// 关闭
conn.close();
}
@Test
// 2. 【推荐】配置方式实现连接池 , 便于维护
public void testProp() throws Exception {
// 加载prop配置文件
Properties prop = new Properties();
// 获取文件流
InputStream inStream = DBCPtest.class.getResourceAsStream("db.properties");
// 加载属性配置文件
prop.load(inStream);
// 根据prop配置,直接创建数据源对象
DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);
// 获取连接
Connection con = dataSouce.getConnection();
con.prepareStatement("delete from admin where id=4").executeUpdate();
// 关闭
con.close();
}
}
db.properties文件
url=jdbc:mysql:///admin?characterEncoding=utf8
driverClassName=com.mysql.jdbc.Driver
username=root
password=0000
initialSize=3
maxActive=6
maxIdle=3000
jdbc:mysql://localhost:3306/admin?characterEncoding=utf8
com.mysql.jdbc.Driver
root
0000
3
6
1000
jdbc:mysql://localhost:3306/admin?characterEncoding=utf8
com.mysql.jdbc.Driver
root
0000
3
6
1000
package work.itcase.c3p0;
import java.sql.Connection;
import java.sql.PreparedStatement;
import org.junit.Test;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0test {
@Test
//1. 硬编码方式,使用C3P0连接池管理连接
public void testCode() throws Exception {
// 创建连接池核心工具类
ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/admin?characterEncoding=utf8");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUser("root");
dataSource.setPassword("0000");
dataSource.setInitialPoolSize(3); //初始时获取的三个连接
dataSource.setMaxPoolSize(6); // 最大连接数
dataSource.setMaxIdleTime(1000); // 最大空闲时间
// ---> 从连接池对象中,获取连接对象
Connection conn = dataSource.getConnection();
// 执行更新
conn.prepareStatement("delete from admin where id=1").executeUpdate();
// 关闭
conn.close();
}
@Test
//2. XML配置方式,使用C3P0连接池管理连接
public void testXML() throws Exception {
// 创建c3p0连接池核心工具类
// 自动加载src下c3p0的配置文件【c3p0-config.xml】
ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置
PreparedStatement pstmt = null;
// 获取连接
Connection conn = dataSource.getConnection();
for (int i=1; i<11;i++){
String sql = "insert into admin(username,pwd) values(?,?)";
// 执行更新
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "Rose" + i);
pstmt.setString(2, "0000");
pstmt.executeUpdate();
}
pstmt.close();
// 关闭
conn.close();
}
}
查看活跃的l连接列表
SHOW PROCESSLIST