数据库连接池
一、JDBC和 DBCP的比较(纯个人感受)
使用JDBC连接数据库,每次到都需要手工创建连接,并且访问一次数据库就要创建一个连接,dbcp访问,连接隐藏,只需要获取连接,就行,初始化连接数量,可以从池中获得,连接,超出之后回创建连接。这一方面减轻工作,另一方面可提升性能。
DBCP很多web服务器基本都有实现连接池。一般称为DataSource数据源,数据源包含蓝数据连接池的实现。还有一些开源组织也有数据源的实现:
DBCP、C3P0、Tomcat内置连接池
二、各个连接池的实现
DBCP:
commons-dbcp-1.4.jar:连接池的实现。
commons-pool-1.6.jar:连接池实现的依赖库。
创建相关的资源文件:dbcp.config
#
连接设置
driverClassName=com.mysql.jdbc.Driver
url=
jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=
lxj
password=
123456
#<!--
初始化连接
-->
initialSize=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_COMMITTED
publicclassDbcpUtils {
privatestaticjavax.sql.DataSource ds= null;
static{
try{
Properties props= newProperties();
props.load(DbcpUtils.class.getClassLoader().getResourceAsStream("dbcp.properties"));
BasicDataSourceFactoryfactory= newBasicDataSourceFactory();
ds= factory.createDataSource(props);
}catch(IOException e){
//TODOAuto-generated catch block
e.printStackTrace();
}catch(Exception e){
//TODOAuto-generated catch block
e.printStackTrace();
}
}
publicstaticConnection getConnection() throwsSQLException {
returnds.getConnection();//不会将真正的MySQL驱动返回的Connection返回给你
}
publicstaticvoidrelease(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close();//假设throw异常
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
rs= null;//假设rs对象没有释放,将其置为null,该对象就变成垃圾,由Java垃圾回收器回收
}
if(st!=null){
try{
st.close();//假设throw异常
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
st= null;
}
if(conn!=null){
try{
conn.close();
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
}
}
}
2、C3P0学习
首先,有两种方式可以实现配置数据源,一种代码实现,一种是结合JNDI实现的,两种方式中推荐的是第二种,可以解耦,易于维护。C3P0的配置文件名必须是c3p0-config.xml,具体内容如下:
<?xmlversion="1.0"encoding="UTF-8"?>
<c3p0-config>
<!--
C3P0的缺省(默认)配置,
如果在代码中“ComboPooledDataSourceds= new ComboPooledDataSource();”这样写就表示使用的是C3P0的缺省(默认)配置信息来创建数据源
-->
<default-config>
<!--C3P0的属性:driverClass-->
<propertyname="driverClass">com.mysql.jdbc.Driver</property>
<propertyname="jdbcUrl">
<!--如果使用;分割的话提示你不对,只能是用&才能正常的连接-->
<![CDATA[
jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=UTF8
]]>
</property>
<propertyname="user">lxj</property>
<propertyname="password">123456</property>
<propertyname="initialPoolSize">10</property>
<propertyname="maxIdleTime">30</property><!--最大空闲时间-->
<propertyname="maxPoolSize">20</property>
<propertyname="minPoolSize">10</property>
<propertyname="maxStatements">200</property>
</default-config>
<!--
C3P0的命名配置,
如果在代码中“ComboPooledDataSourceds= new ComboPooledDataSource("mysql");”这样写就表示使用的是name是mysql的配置信息来创建数据源
-->
<named-configname="mysql">
<propertyname="acquireIncrement">50</property>
<propertyname="initialPoolSize">100</property>
<propertyname="minPoolSize">50</property>
<propertyname="maxPoolSize">1000</property><!--intergalactoApp adopts a different approach to configuring statement
caching-->
<propertyname="maxStatements">0</property>
<propertyname="maxStatementsPerConnection">5</property><!--he's important, but there's only one of him -->
</named-config>
<named-configname="oracle">
<propertyname="acquireIncrement">50</property>
<propertyname="initialPoolSize">100</property>
<propertyname="minPoolSize">50</property>
<propertyname="maxPoolSize">1000</property><!--intergalactoApp adopts a different approach to configuring statement
caching-->
<propertyname="maxStatements">0</property>
<propertyname="maxStatementsPerConnection">5</property><!--he's important, but there's only one of him -->
</named-config>
</c3p0-config>
数据源创建代码如下:
publicstaticComboPooledDataSource ds= null;
//静态代码块只执行一次,因为静态代码块在类加载时执行,类永远只加载一次
static{
//初始化连接池
try{
//通过读取C3P0的xml配置文件创建数据源,C3P0的xml配置文件c3p0-config.xml必须放在src目录下
ds= newComboPooledDataSource(); //使用配置文件的缺省配置,配置文件名称必须是c3p0-config.xml
//通过代码创建C3P0数据库连接池
/*
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16");
ds.setUser("root");
ds.setPassword("yezi");
ds.setMaxPoolSize(30);
ds.setMinPoolSize(5);
ds.setInitialPoolSize(10);
*/
}catch(Exception e){
thrownewExceptionInInitializerError(e);
}
}
publicstaticConnection getConnection() throwsSQLException {
returnds.getConnection();//不会将真正的MySQL驱动返回的Connection返回给你
}
publicstaticvoidrelease(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close();//假设throw异常
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
rs= null;//假设rs对象没有释放,将其置为null,该对象就变成垃圾,由Java垃圾回收器回收
}
if(st!=null){
try{
st.close();//假设throw异常
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
st= null;
}
if(conn!=null){
try{
conn.close();
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
}
}
}
3、tomcat内置的数据源
我们有时候还会使用服务器提供给我们的数据库连接池,比如我们希望Tomcat服务器在启动的时候可以帮我们创建一个数据库连接池,那么我们在应用程序中就不需要手动去创建数据库连接池,直接使用Tomcat服务器创建好的数据库连接池即可。
JNDI-Java命名和目录接口,它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需通过名称检索即可。其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象。
配置tomcat数据源:
1、webContent下的MATA-INF新建context.xml文件。
<?xmlversion="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/EmployeeDB"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="yezi"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/day16"
initialSize="10"
maxActive="30"
maxIdle="4"/>
</Context>
2、将数据库驱动文件放入tomcat的lib之下
3、程序
privatestaticDataSource ds= null;
static{
try{
Contextinitctx= newInitialContext();
ContextenvCtx= (Context) initctx.lookup("java:comp/env");
ds= (DataSource) envCtx.lookup("jdbc/lxjDB");
}catch(NamingException e){
//TODOAuto-generated catch block
e.printStackTrace();
}
}
publicstaticConnection getConnection() throwsSQLException {
returnds.getConnection();
}
publicstaticvoidrelease(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close();//假设throw异常
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
rs= null;//假设rs对象没有释放,将其置为null,该对象就变成垃圾,由Java垃圾回收器回收
}
if(st!=null){
try{
st.close();//假设throw异常
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
st= null;
}
if(conn!=null){
try{
conn.close();
}catch(Exception e){
e.printStackTrace();//只需在后台记录异常
}
}
}