数据库连接池:说白了就是在一个池子中(容器)中放了很多的数据库连接,当用户需要的时候就从中取出来一个用,用完了就放回连接池中。
优点:极大的提高了数据库的效率。
对于自定义的数据库连接池我们使用一个LinkedList做数据库连接池.这个集合的特点是增删快,查询慢。
自定义一个数据库连接池的步骤:
1.自定义一个类实现DataSource接口。
2.定义一个List<Connection> list=new LinkedList<Connection>();存放数据库连接。
3.初始化数据库连接池。就是在静态代码块static块中添加数据库的连接若干到list中(连接池)。
4.写一个方法returnPool(Connection con)还回到数据库连接池。如果数据库连接池中没有数据连接可用,就添加若干个带数据库连接池list中。
5.在getConnection()方法中动态代理重新改造Connection的close方法,因为我们不能够用完了就关闭,而是应该用完了还回数据库连接池中。这样可以循环使用。
案例:
自定义自己的数据库连接池MyPool
package com.itheima.mypools;
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.List;
import java.util.logging.Logger;
import javax.sql.DataSource;
public class MyPool implements DataSource{
//1.需要一个容器存放连接
private static List<Connection> list=new LinkedList<Connection>();
//初始化加载类的时候就在连接池中添加了5个连接
static{
try {
//2.加载驱动
Class.forName("com.mysql.jdbc.Driver");
for(int i=0;i<5;i++){
//3.获取连接
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "169500");
list.add(con);
}
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
@Override
public Connection getConnection() throws SQLException {
//如果连接池的数据没有了就添加3个连接到连接池中
if(list.size()==0){
for(int i=0;i<3;i++){
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/day11", "root", "169500");
list.add(con);
}
}
//获取连接,就是把连接池中的连接remove不是get...
final Connection con = list.remove(0);
//需要重写连接的close()方法,我们使用动态代理
Connection proxy=(Connection) Proxy.newProxyInstance(con.getClass().getClassLoader(), con.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)//proxy代理类对象 method被代理类的方法,args被代理类方法的参数
throws Throwable {
if("close".equals(method.getName())){
//要改造的方法就还回连接池
returnPool(con);
return null;
}else{
//不想改造的方法就使用被代理者对象的方法
return method.invoke(con, args);
}
}
});
System.out.println("获取了一个连接,连接池中还有:"+list.size()+"个连接");
return proxy;
}
public void returnPool(Connection con){
try {
if(con!=null&&!con.isClosed()){
list.add(con);
}
} catch (SQLException e) {
e.printStackTrace();
}
System.out.println("还回了一个连接,池里还剩余"+list.size()+"个连接");
}
@Override
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO Auto-generated method stub
return null;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
}
使用这个自己定义的数据库连接池:
package com.itheima.mypools;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import cn.itheima.utils.JDBCUtils;
public class JDBCDemo1 {
public static void main(String[] args) {
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
//使用数据库连接池
MyPool pool=new MyPool();
//获取连接
con=pool.getConnection();
ps=con.prepareStatement("select * from account");
rs=ps.executeQuery();
while(rs.next()){
String name=rs.getString("name");
System.out.println(name);
}
} catch (SQLException e) {
e.printStackTrace();
throw new RuntimeException();
}finally{
//这里的close已经被更该过了
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs=null;
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
ps=null;
}
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
con=null;
}
}
}
}
}
运行结果: