一、应用程序直接连接数据库缺点
用户每次请求都需要向数据库获取连接,而数据库创建连接通常需要消耗较大的资源,消耗的时间也比较长。
二、使用数据库连接池优化程序性能
1、数据库连接池基本概念
数据库连接池负责连接、管理和释放数据库连接,它允许程序重复使用一个现有的数据库连接而不是新建一个。
最小连接数:连接池一直保持的数据库连接的最小数目。
最大连接数:连接池所能申请的最大连接数目。
2、编写数据库连接池
编写数据库连接池需要实现java.sql.DataSource接口。该接口重载了两个getConnection方法。
getConnection();
getConnection(String name,String password);
实现DataSource接口并实现连接池功能的步骤:
1) 在DataSource函数中批量创建与数据库的连接,并把创建的连接加入到LinkedList对象中。
2) 实现getConnection方法,让getConnection方法每次调用时,从LinkedList中取出一个Connection返回给用户。
3) 当用户使用完Connection,调用Connection.close()方法时,Connection对象应保证将自己返回到LinkedList中,而不是把Connection返还给数据库。
代码:
public class JdbcPool implements DataSource{
//由于要频繁读取List,因此使用LinkedList存储数据库连接比较合适
private static LinkedList<Connection> listConnections = new LinkedList<Connection>();
//在静态代码块中加载db.properties配置文件
static{
InputStream in = JdbcPool.class.getClassLoader().getResourceAsStream("db.properties");
Properties prop = new Properties();
try{
prop.load(in);
//获取文件中的属性值
//mysql:driver = com.jdbc.mysql.Driver
//Oracle:driver = Oracle.jdbc.driver.OracleDriver
String driver = prop.getProperty("driver");
//mysql:url = jdbc:mysql://localhost:3306/数据库名称
//Oracle:url = jdbc:oracle:thin:@localhost:1521:orcl
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
//数据库连接池初始化连接池大小
int jdbcInitSize = Integer.parseInt(prop.getProperty("jdbcPoolInitSize"));
//加载数据库驱动
Class.forName(driver);
for(int i = 0;i<jdbcInitSize;i++){
Connection conn = DriverManager.getConnection(url,username,password);
listConnections.add(conn);
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
}
//获取数据库连接
public Connection getConnection() throws SQLException{
//如果数据库连接池中的连接对象大于0
if(listConnections.size()>0){
//从listConnections中取一个数据库连接,用final修饰
//LinkedList.removeFirst():移除并返回LinkedList的第一个元素。
final Connection conn = listConnections.removeFirst();
//返回Connecion的代理对象
return (Connection) Proxy.newProxyInstance(
JdbcPool.class.getClassLoader(),
conn.getClass().getInterfaces(),
new InvocationHandler(){
public Object invoke(Object proxy,Method method,Object[] args) throws Thowable{
if(!method.getName.equals("close")){
return invoke(conn,args);
}else{
//如果调用的是close方法,就把conn返回给数据库连接池
listConnections.add(conn);
return null;
}
}
});
}else{
throw new RunTimeException("数据库忙!");
}
}
}