(一)JDBC连接池&DBUtils—自定义连接池
1.案例分析
在实习开发中“获取链接”或“释放连接”是非常消耗资源的两个过程,为了解决此类性能问题,通常情况下采用连接池技术,来共享连接Connection。
2.用池来管理Connection
这样可以重复使用Connection。有了池,所以我们就不用来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了
3.自定义连接池
①编写自定义连接池步骤
1.创建连接池实现(数据源),并实现借口javax.sql.DataSource。因为我们只使用该接口中getConnection()方法,简化本案例,将自己提供方法,而没有实现接口
2.提供一个集合,用于存放连接,因为我们移除/添加操作过多,选择LinkedList
3.本案例在静态代码块中,为连接池初始化5个连接。
4.之后程序如果需要连接,调用实现类的getConnection(),本方法将从连接池获得连接。为了保证当前连接只能提供给一个线程使用,所以需要将连接先从连接池中移除
5.用户使用连接,释放资源,不执行close()方法,而是将连接添加到连接池中
②案例代码演示
1.提供容器及初始化
6.//1.创建一个容器存储Connection对象 7. private static LinkedList<Connection> pool=new LinkedList<Connection>(); 8. //2.创建一个五个连接加入到容器中 9. static{ 10. for(int i=0;i<5;i++){ 11. Connection conn= JDBCUtils_V3.getConnection(); 12. pool.add(conn); 13. } } |
2.获取连接
14./** 15. * 重写获取链接的方法 16. */ 17. @Override 18. public Connection getConnection() throws SQLException { 19. Connection conn=null; 20. //3.使用连接词前先进行判断连接池是否为空 21. if(pool.size()==0){ 22. //4.如果池子里面没有需要添加一下 23. for(int i=0;i<5;i++){ 24. conn= JDBCUtils_V3.getConnection(); 25. pool.add(conn); 26. } 27. } 28. //5.从池子里面获取一个链接对象 29. conn=pool.remove(0); 30. return conn; 31. } |
3.归还链接
32./** 33. * 归还连接对象到连接池 34. */ 35. public void backConnection(Connection conn){ 36. pool.add(conn); 37. } 38. |
自定义连接池代码
package cn.itheima.jdbc.DataSource;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;
import javax.sql.DataSource;
import cn.itheima.jdbc.JDBCUtils_V3;
public class MyDataSource implements DataSource{
//1.创建一个容器存储Connection对象
private static LinkedList
pool=new LinkedList
();
//2.创建一个五个连接加入到容器中
static{
for(int i=0;i<5;i++){
Connection conn= JDBCUtils_V3.getConnection();
pool.add(conn);
}
}
/**
* 重写获取链接的方法
*/
@Override
public Connection getConnection() throws SQLException {
Connection conn=null;
//3.使用连接词前先进行判断连接池是否为空
if(pool.size()==0){
//4.如果池子里面没有需要添加一下
for(int i=0;i<5;i++){
conn= JDBCUtils_V3.getConnection();
pool.add(conn);
}
}
//5.从池子里面获取一个链接对象
conn=pool.remove(0);
return conn;
}
/**
* 归还连接对象到连接池
*/
public void backConnection(Connection conn){
pool.add(conn);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@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 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 boolean isWrapperFor(Class
iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
@Override
public
T unwrap(Class
iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
}
测试类代码
/**
* 使用未改造过的连接池方法添加用户
*/
@Test
public void testAddUser() {
Connection conn = null;
PreparedStatement pstmt = null;
// 1.创建自定义连接池对象
MyDataSource dataSource = new MyDataSource();
try {
// 2.从池子中获取连接
conn = dataSource.getConnection();
String sql = "insert into tbl_user values(null,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, "吕布");
pstmt.setString(2, "貂蝉");
int rows = pstmt.executeUpdate();
if (rows > 0) {
System.out.println("添加成功!");
} else {
System.out.println("添加失败!");
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
dataSource.backConnection(conn);
}
}