Java连接MySql用DBCP连接池的实现
DBCP1.4或1.6
依赖的jar包
image.pngDBCP参数说明
参数 | 默认值 | 说明 |
---|---|---|
username | root | 传递给JDBC驱动的用于建立连接的用户名 |
password | root | 传递给JDBC驱动的用于建立连接的密码 |
url | jdbc:mysql://localhost:3306/adname | 传递给JDBC驱动的用于建立连接的URL |
driverClassName | com.mysql.jdbc.Driver | 使用的JDBC驱动的完整有效的Java 类名 |
initialSize | 0 | 初始化连接:连接池启动时创建的初始化连接数量,1.2版本后支持 |
maxActive | 8 | 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量, 如果设置为非正数则表示不限制 |
maxIdle | 8 | 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制 |
minIdle | 0 | 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建 |
maxWait | 无限 | 最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数)超过时间则抛出异常,如果设置为-1表示无限等待 |
testOnReturn | false | 是否在归还到池中前进行检验 |
testWhileIdle | false | 连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.设置为true后如果要生效,validationQuery参数必须设置为非空字符串 |
minEvictableIdleTimeMillis | 1000 * 60 * 30 | 连接在池中保持空闲而不被空闲连接回收器线程(如果有)回收的最小时间值,单位毫秒 |
numTestsPerEvictionRun | 3 | 在每次空闲连接回收器线程(如果有)运行时检查的连接数量 |
timeBetweenEvictionRunsMillis | -1 | 在空闲连接回收器线程运行期间休眠的时间值,以毫秒为单位.如果设置为非正数,则不运行空闲连接回收器线程 |
validationQuery | null | SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录 |
testOnBorrow | true | 是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个. |
代码
DBToolls.java文件
package cn.doudou.tools;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
public class DB {
//建立连接的驱动驱动名称
public static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
//数据库链接数据哭的url
public static final String URL = "jdbc:mysql://localhost:3306/person";
//链接的数据库账号
public static final String USERNAME = "root";
//链接的数据库密码
public static final String PASSWORD = "root";
//最大空闲链接
private static final int MAX_IDLE = 3;
//醉的等待时间
private static final long MAX_WAIT = 5000;
//最大活动链接
private static final int MAX_ACTIVE = 5;
//初始化时链接池的数量
private static final int INITIAL_SIZE = 10;
//的到链接实例
private static BasicDataSource dataSource = new BasicDataSource();
//初始化链接参数
static{
dataSource.setDriverClassName(DRIVER_CLASS_NAME);
dataSource.setUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
dataSource.setMaxActive(MAX_IDLE);
dataSource.setMaxWait(MAX_WAIT);
dataSource.setMaxActive(MAX_ACTIVE);
dataSource.setInitialSize(INITIAL_SIZE);
}
//提供获得数据源
public static DataSource getDateSource(){
return dataSource;
}
//提供获得链接
public static Connection getConnection() throws SQLException{
return dataSource.getConnection();
}
}
测试test.java
package cn.doudou.test;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import cn.doudou.tools.DB;
public class test {
public static void main(String[] args) {
try {
Connection conn=DB.getDateSource().getConnection();
System.out.println(conn);
String sql="select id,name,age,sex from person";
Statement s=conn.createStatement();
ResultSet rs=s.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getInt("id")+" "+rs.getString("name")+" "
+rs.getInt("age")+" "+rs.getString("sex"));
System.out.println("----------------");
}
rs.close();
s.close();
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行结果
image.pngDBCP2以上版本
依赖的jar包
image.pngDBCP2配置详细说明
由于commons-dbcp所用的连接池出现版本升级,因此commons-dbcp2中的数据库池连接配置也发生了变化,具体的参数配置说明如下:
常用连接配置
参数 | 描述 |
---|---|
username(用户名) | 通过JDBC建立一个连接所需的用户名 |
password(密码) | 通过JDBC建立一个连接所需的密码 |
url(JDBC连接串) | 通过JDBC建立一个连接所需的URL |
driverClassName(JDBC驱动程序) | 所使用的JDBC驱动的类全名 |
connectionProperties(连接属性) | 连接参数是在建立一个新连接时发送给JDBC驱动的。字符串的格式必须是[参数名=参数值;]。提示:用户名和密码属性是需要明确指出的,所以这两个参数不需要包含在这里 |
数据源连接数量配置
参数 | 缺省值 | 描述 |
---|---|---|
initialSize(初始连接数) | 0 | 当这个池被启动时初始化的创建的连接个数,起始生效版本:1.2 |
maxTotal(最大活动连接数) | 8 | 可以在这个池中同一时刻被分配的有效连接数的最大值,如设置为负数,则不限制 |
maxIdle(最大空闲连接数) | 8 | 在池中,可以保持空闲状态的最大连接数,超出设置值之外的空闲连接在归还到连接池时将被释放,如设置为负数,则不限制 |
minIdle(最小空闲连接数) | 0 | 可以在池中保持空闲的最小连接数,低于设置值时,空闲连接将被创建,以努力保持最小空闲连接数>=minIdle,如设置为0,则不创建。这里设置的数值生效的前提是:timeBetweenEvictionRunsMillis(空闲对象驱逐线程运行时的休眠毫秒数)被设置为正数。 |
maxWaitMillis(从连接池获取一个连接时,最大的等待时间) | indefinitely(不确定) | 设置为-1时,如果没有可用连接,连接池会一直无限期等待,直到获取到连接为止。如果设置为N(毫秒),则连接池会等待N毫秒,等待不到,则抛出异常。 |
提示: 如果在高负载的系统中将maxIdle的值设置的很低,则你可能会发现在一个新的连接刚刚被创建的时候就立即被关闭了。这是活跃的线程及时关闭连接要比那些打开连接的线程要快,导致空闲的连接数大于maxIdle。高负载系统中maxIdle的最合适的配置值是多样的,但是缺省值是一个好的开始点。
事务属性配置
参数 | 缺省值 | 描述 |
---|---|---|
defaultAutoCommit(自动提交) | JDBC驱动的缺省值 | 通过这个池创建连接的默认自动提交状态。如果不设置,则setAutoCommit 方法将不被调用。 |
defaultReadOnly(只读设置) | JDBC驱动的缺省值 | 通过这个池创建连接的默认只读状态。如果不设置,则setReadOnly 方法将不被调用。(部分驱动不支持只读模式,如:Informix) |
defaultTransactionIsolation(事务隔离级别) | JDBC驱动的缺省值 | 通过这个池创建连接的默认事务隔离策略,设置值为下列中的某一个: NONE、 READ_COMMITTED、 READ_UNCOMMITTED、 REPEATABLE_READ、 SERIALIZABLE |
defaultCatalog(目录,类似于与模式名,但比模式名更加抽象,Oracle、MySQL不支持,其他,MS SQL Server = 数据库名) | 通过这个池创建连接的默认缺省的catalog | |
cacheState(缓存状态) | true | 如果设置为true,池化的连接将在第一次读或写,以及随后的写的时候缓存当前的只读状态和自动提交设置。这样就省去了对getter的任何进一步的调用时对数据库的额外查询。如果直接访问底层连接,只读状态和/或自动提交设置改变缓存值将不会被反映到当前的状态,在这种情况下,应该将该属性设置为false以禁用缓存。 |
defaultQueryTimeout(查询超时时间) | null | 如果值不为null,指定一个整数值,用于在创建Statement时,指定为查询超时时间。如果设置为null,则使用驱动程序默认设置。 |
enableAutocommitOnReturn(连接归还到池时,设置为自动提交) | true | 如果设置为true,则连接被归还到连接池时,会指定设置为autoCommit = true |
rollbackOnReturn(连接归还到池时,回滚所有操作) | true | 如果设置为true,则连接被归还到连接池时,会自动执行一次rollback();前提是自动提交 = true and 非只读。 |
数据源连接健康状况检查
参数 | 缺省值 | 描述 |
---|---|---|
validationQuery(确认查询SQL) | 在连接池返回连接给调用者前用来进行连接校验的查询sql。如果指定,则这个查询必须是一个至少返回一行数据的SQL SELECT语句。如果没有指定,则连接将通过调用isValid() 方法进行校验。 | |
validationQueryTimeout(确认查询SQL的超时时间) | no timeout | 确认连接有效SQL的执行查询超时时间(秒)。如果设置为正数,那么会传递给JDBC驱动的setQueryTimeOut()方法,这个设置对执行【确认有效查询SQL】起作用。 |
testOnCreate(连接创建后,马上验证有效性) | false | 指明对象在创建后是否需要验证是否有效,如果对象验证失败,则触发对象创建的租借尝试将失败。 |
testOnBorrow(从连接池获取一个连接时,验证有效性) | true | 指明在从池中租借对象时是否要进行验证有效,如果对象验证失败,则对象将从池子释放,然后我们将尝试租借另一个 |
testOnReturn(连接被归还到连接池时,验证有效性) | false | 指明在将对象归还给连接池前是否需要校验。 |
testWhileIdle(连接空闲时,验证有效性) | false | 指明对象是否需要通过对象驱逐者进行校验(如果有的话),假如一个对象验证失败,则对象将被从池中释放。 |
timeBetweenEvictionRunsMillis(空闲对象驱逐线程运行时的休眠毫秒数) | -1 | 空闲对象驱逐线程运行时的休眠毫秒数,如果设置为非正数,则不运行空闲对象驱逐线程。 |
numTestsPerEvictionRun(在每个空闲对象驱逐线程运行过程中中进行检查的对象个数) | 3 | 在每个空闲对象驱逐线程运行过程中中进行检查的对象个数。(如果有的话) |
minEvictableIdleTimeMillis(空闲的连接最低要待N毫秒后,才会被释放) | 1000 * 60 * 30(30分) | 符合对象驱逐条件的对象在池中最小空闲毫秒总数(如果有的话) |
softMiniEvictableIdleTimeMillis(空闲的连接最低要待N毫秒后,才会被释放,但有额外条件) | -1 | 符合对象驱逐条件的对象在池中最小空闲毫秒总数,额外的条件是池中至少保留有minIdle所指定的个数的连接。当miniEvictableIdleTimeMillis 被设置为一个正数,空闲连接驱逐者首先检测miniEvictableIdleTimeMillis,当空闲连接被驱逐者访问时,首先与miniEvictableIdleTimeMillis 所指定的值进行比较(而不考虑当前池中的空闲连接数),然后比较softMinEvictableIdleTimeMillis所指定的连接数,包括minIdle条件。 |
maxConnLifetimeMillis(一个连接的最大存活毫秒数) | -1 | 一个连接的最大存活毫秒数。如果超过这个时间,则连接在下次激活、钝化、校验时都将会失败。如果设置为0或小于0的值,则连接的存活时间是无限的。 |
connectionInitSqls(连接被第一次创建时,执行的初始化SQL) | nullt | 在第一次创建时用来初始化物理连接的SQL语句集合。这些语句只在配置的连接工厂创建连接时被执行一次 |
lifo(后进先出) | true | 设置为true表明连接池(如果池中有可用的空闲连接时)将返回最后一次使用的租借对象(最后进入)。设置为false则表明池将表现为FIFO队列(先进先出)—将会按照它们被归还的顺序从空闲连接实例池中获取连接 |
logExpiredConnections(一个过期的连接被连接池关闭时,写日志标识) | true | 如果连接存货时间超过maxConnLifetimeMillis,连接将被连接池会抽,此时默认输出日志。如果设置为false,这不会写日志。 |
缓存语句
参数 | 缺省值 | 描述 |
---|---|---|
poolPreparedStatements(设置该连接池的预处理语句池是否生效) | false | 设置该连接池的预处理语句池是否生效 |
maxOpenPreparedStatements(可以在语句池中同时分配的最大语句数) | unlimited | 可以在语句池中同时分配的最大语句数。设置为负数则不限制。 |
这个设置同时作用于预处理语句池. 当一个可用的语句池被创建给每一个连接时,通过以下方法创建的预处理语句将被池化。
- public PreparedStatement prepareStatement(String sql)
- public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
提示 -要确保你的连接会留下一些资源给其他语句。池化预处理语句可能会在数据库中保持他们的游标,可能会引起连接的游标越界,尤其是maxOpenPreparedStatements的值被设置为默认值(无限的),而且一个应用程序可能会为每个连接打开大量不同的预处理语句。为了避免这个问题maxOpenPreparedStatements应该被设置为一个小于连接可以打开的最大游标数的值。
参数 | 缺省值 | 描述 |
---|---|---|
accessToUnderlyingConnectionAllowed(控制PoolGuard是否可以访问底层连接 ) | false | 控制PoolGuard是否可以访问底层连接 |
如果允许访问的话,使用如下代码结构:
Connection conn = ds.getConnection();
Connection dconn =((DelegatingConnection) conn).getInnermostDelegate();
...
conn.close()
默认值为false,这是一个有着潜在风险的操作,使用不当可能会导致非常严重的后果。(在守护连接已被关闭的情况下,关闭底层连接或者继续使用它),只有在你需要直接访问驱动的特有扩展是可以谨慎使用。
NOTE: 除了最原始那个之外,不要关闭底层连接
参数 | 缺省值 | 描述 |
---|---|---|
removeAbandoned | false | 标记是否删除超过removeAbandonedTimout所指定时间的被遗弃的连接。如果设置为true,则一个连接在超过removeAbandonedTimeout所设定的时间未使用即被认为是应该被抛弃并应该被移除的。创建一个语句,预处理语句,可调用语句或使用它们其中的一个执行查询(使用执行方法中的某一个)会重新设置其父连接的lastUsed 属性。在写操作较少的应用程序中将该参数设置为true可以将数据库连接从连接关闭失败中恢复。 |
removeAbandonedTimeout(一个被抛弃连接可以被移除的超时时间) | 300(秒) | 一个被抛弃连接可以被移除的超时时间,单位为秒 |
logAbandoned | false | 标志是否为应用程序中遗弃语句或连接的代码开启日志堆栈追踪。因为一个堆栈跟踪已被创建,被抛弃的语句和连接相关的日志将被覆盖到打开每个连接或者创建一个Statement时 |
如果你启用了removeAbandoned,则一个连接被池回收再利用是可能的,因为它被认为是已遗弃 在(getNumIdle() < 2) and (getNumActive() > getMaxTotal() - 3)成立时,这个机制将被触发。
例如, maxTotal=20 ,这里有18个活跃连接,一个限制连接,将触发 "removeAbandoned"。但是只有在活动连接超过 "removeAbandonedTimeout" 所指定的秒数内未使用才会被删除(默认为300秒)。遍历一个结果集并不被统计为被使用,创建一个语句,预处理语句,可调用语句或使用它们其中的一个执行查询(使用执行方法中的某一个)会重新设置其父连接的lastUsed 属性。
连接泄露回收
参数 | 缺省值 | 描述 |
---|---|---|
fastFailValidation(验证快速失败) | false | 如果发生致命的异常,验证语句会快速失败。而不会再执行isValid(),也不再去执行验证查询语句。致命的异常码(SQL_STATE)指以下:57P01 (ADMIN SHUTDOWN)、57P02 (CRASH SHUTDOWN)、57P03 (CANNOT CONNECT NOW)、01002 (SQL92 disconnect error)、JZ0C0 (Sybase disconnect error)、JZ0C1 (Sybase disconnect error)、Any SQL_STATE code that starts with "08" |
disconnectionSqlCodes(异常码) | anull | 以逗号分割的SQL_STATE码,fastFailValidation 为true时,才会生效。 |
代码
DB2.java文件
import org.apache.commons.dbcp2.BasicDataSource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
public class DB2 {
//建立连接的驱动驱动名称
public static final String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";
//数据库链接数据哭的url
public static final String URL = "jdbc:mysql://localhost:3306/person";
//链接的数据库账号
public static final String USERNAME = "root";
//链接的数据库密码
public static final String PASSWORD = "root";
//最大空闲链接
private static final int MAX_IDLE = 20;
//最大空闲连接
private static final int MinIdle=8;
//最大等待时间
private static final long MAX_WAIT_Millis = 5000;
//最大活动链接
private static final int MAX_TOTAl = 5;
//初始化时链接池的数量
private static final int INITIAL_SIZE = 10;
//一个被抛弃连接可以被移除的超时时间
private static final int RemoveAbandonedTimeout=180;
//只会发现当前连接失效,再创建一个连接供当前查询使用
private static final boolean TOBESTNORROW =true;
private static BasicDataSource DATA_SOURCE;
static {
DATA_SOURCE=new BasicDataSource();
DATA_SOURCE.setDriverClassName(DRIVER_CLASS_NAME);
DATA_SOURCE.setUrl(URL);
DATA_SOURCE.setUsername(USERNAME);
DATA_SOURCE.setPassword(PASSWORD);
DATA_SOURCE.setMaxTotal(MAX_TOTAl);
DATA_SOURCE.setInitialSize(INITIAL_SIZE);
DATA_SOURCE.setMinIdle(MinIdle);
DATA_SOURCE.setMaxIdle(MAX_IDLE);
DATA_SOURCE.setMaxWaitMillis(MAX_WAIT_Millis);
DATA_SOURCE.setTestOnBorrow(TOBESTNORROW);
DATA_SOURCE.setRemoveAbandonedTimeout(RemoveAbandonedTimeout);
System.out.println("完成设置数据库连接池DATA_SOURCE的参数!!");
}
//提供获得数据源
public static DataSource getDateSource(){
return DATA_SOURCE;
}
//提供获得链接
public static Connection getConnection() throws SQLException {
return DATA_SOURCE.getConnection();
}
}
test.java文件
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class test {
public static void main(String[] args) {
try {
Connection conn=DB2.getDateSource().getConnection();
String sql="select id,name,age,sex from person";
Statement s=conn.createStatement();
ResultSet rs=s.executeQuery(sql);
while(rs.next()){
System.out.println(rs.getInt("id")+" "+rs.getString("name")+" "
+rs.getInt("age")+" "+rs.getString("sex"));
System.out.println("----------------");
}
rs.close();
s.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}