JDBC中总是创建和删除Connection会导致系统执行效率很低,所以可以使用数据库连接池来加快系统的执行效率,具体做法如下:
1.创建一个LinkedList来存放数据库连接;
2.用静态代码快来建立数据库连接池;
3.按照一般的步骤来获得数据库连接;
4.用proxy来强化数据库连接的close方法;
5.将强化过的conn加入到LinkedList中;
6.现在可以通过getConnection方法来获得数据库连接了;
7.善于使用异常处理来处理可以预料到的问题;
使用动态代理来强化Connection的close方法,代码如下:
package com.jdbc.jdbc;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
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.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.Properties;
import java.util.logging.Logger;
import javax.sql.DataSource;
/**
* 通过动态代理,增强Connection的close方法
* @author Administrator
*
*/
public class MyDataSource implements DataSource{
//定义连接数据库所需要的字段
private static LinkedList<Connection> pool = new LinkedList<Connection>();
private static String driveClassName = null;
private static String url = null;
private static String username = null;
private static String password = null;
//通过配置文件为以上字段赋值
//并构建一个有15个连接的连接池
static{
try {
//加载配置文件
InputStream in = JDBCFactory.class.getClassLoader().getResourceAsStream("dbcfg.properties");
Properties prop = new Properties();
prop.load(in);
driveClassName = prop.getProperty("className");
url = prop.getProperty("url");
username = prop.getProperty("username");
password = prop.getProperty("password");
//加载驱动类
Class.forName(driveClassName);
//在数据库连接池中加入15个数据库连接
for(int i = 0;i<15;i++) {
final Connection conn = DriverManager.getConnection(url,username,password);
System.out.println("conn:" + conn);
System.out.println("interface :" + conn.getClass().getInterfaces().toString());
//代理和Connection使用了同样的接口,所以他们是同样的类型
Connection pconn = (Connection) Proxy.newProxyInstance(MyDataSource.class.getClassLoader(),conn.getClass().getInterfaces(), new InvocationHandler() {
//通过动态代理增强close方法,使得调用close方法时直接将资源还给数据库连接池(使用的是匿名内部类)
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
if(!methodName.equals("close")) {
//关键代码:返回代理类所代理的实例
return method.invoke(conn, args);
}else {
//如果是close方法,将资源还给数据库连接池
pool.addLast(conn);
}
return null;
}
});
System.out.println("pconn:" + pconn);
//数据库连接池里面加入的其实是增强过的数据库连接
pool.add(pconn);
}
}catch (ClassNotFoundException e) {
throw new RuntimeException("Can't find the Class!");
}catch (SQLException e) {
throw new RuntimeException("Can't init connection!");
}catch (IOException e) {
throw new RuntimeException("Can't find the properties!");
}
}
//从数据库连接池里面取得一个连接
@Override
public Connection getConnection() throws SQLException {
if(pool.size() > 0) {
System.out.println(pool.size());
return pool.removeFirst();
}else {
throw new RuntimeException("对不起,服务器忙!");
}
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {}
@Override
public void setLoginTimeout(int seconds) throws SQLException {}
@Override
public int getLoginTimeout() throws SQLException {
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return false;
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return null;
}
}
使用c3p0实现数据库连接池:
1、拷贝jar包
在c3p0发行包的lib目录中
c3p0-0.9.1.2.jar
c3p0-0.9.1.2-jdk1.3.jar
c3p0-oracle-thin-extras-0.9.1.2.jar(oracle)
2、在类路径下创建一个名为c3p0-config.xml的配置文件
<c3p0-config>
<named-config name="day14">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///day14</property>
<property name="user">root</property>
<property name="password">sorry</property>
<property name="acquireIncrement">10</property>
<property name="initialPoolSize">30</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">40</property>
<property name="maxStatements">1000</property>
<property name="maxStatementsPerConnection">100</property>
</named-config>
</c3p0-config>
3、建立一个工具类,根据配置文件获取数据源
private static ComboPooledDataSource ds = new ComboPooledDataSource ("day14");
public static Connection getConn() throws SQLException{
return ds.getConnection();
}
四、在Tomcat中配置数据源
1、在web应用的META-INF目录下建立一个Context.xml的配置文件
<Context>
<Resource name="jdbc/day14"
auth="Container"
type="javax.sql.DataSource"
username="root"
password="sorry"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql:///day14"
maxActive="8"
maxIdle="4"/>
</Context>
2、需要把数据库驱动拷贝到TOmcat安装目录/lib中(不拷贝,会出现找不到驱动的错误)
3、在需要使用数据源时,利用JNDI技术获取数据源的名称