1、 问题的产生:
过河问题:过一次河,就建一次桥,过完河就销毁。(资源消耗极大)
2、 解决问题(用连接池处理(也叫“数据源处理”)):
《实战》
1、新建MyPool.java:
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;
//1、新建一个类,实现DataSource接口(开发连接池都需要继承这个类)
public class MyPool implements DataSource {
//2、获得一个连接池
private static List<Connection> pool = new LinkedList<Connection>();
static{
try{
Class.forName("com.mysql.jdbc.Driver");
for(int i=0;i<5;i++){
Connection conn = DriverManager.getConnection("jdbc:mysql:///day11","root","root");
pool.add(conn);//添加5个连接到池里面
}
}catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
//3、连接池管理(借出、还回、相关判断处理)
public Connection getConnection() throws SQLException {
if(pool.size()==0){//如果连接池没有连接了
for(int i=0;i<3;i++){
Connection conn = DriverManager.getConnection("jdbc:mysql:///day11","root","root");
pool.add(conn);//往连接池中添加连接
}
}
final Connection conn = pool.remove(0);//在池中拿走一个给conn连接,+(内部类调用外部类的对象,外部类必须是final)
//--1、利用动态代理改造close方法,方便还回连接
Connection proxy = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler(){
public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {
if("close".equals(method.getName())){
//2、对于想要改造的close方法,我们自己写
retConn(conn);
return null;
}else{
//2、对于不想改造的方法调用被代理者身上相同的方法
return method.invoke(conn, args);
}
}
});
System.out.println("获取了一个连接,池里还剩余"+pool.size()+"个连接");
return proxy;//返回代理
}
//还回连接方法(在动态代理中改造嵌入)
private void retConn(Connection conn){
try {
if(conn!=null && !conn.isClosed()){//Connection不为空,并且使用后没有关闭
pool.add(conn);
System.out.println("还回了一个连接,池里还剩余"+pool.size()+"个连接");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//方法重写
public Connection getConnection(String username, String password)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PrintWriter getLogWriter() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public int getLoginTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
public void setLogWriter(PrintWriter out) throws SQLException {
// TODO Auto-generated method stub
}
public void setLoginTimeout(int seconds) throws SQLException {
// TODO Auto-generated method stub
}
public boolean isWrapperFor(Class<?> iface) throws SQLException {
// TODO Auto-generated method stub
return false;
}
public <T> T unwrap(Class<T> iface) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
// TODO Auto-generated method stub
return null;
}
}
2、新建 JDBCDemo1.java:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.itheima.pool.MyPool;
public class JDBCDemo1 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
MyPool pool = new MyPool();
try{
conn = pool.getConnection();
ps = conn.prepareStatement("select * from account");
rs = ps.executeQuery();
while(rs.next()){
String name = rs.getString("name");
System.out.println(name);
}
}catch (Exception e) {
e.printStackTrace();
}finally{
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(conn!=null){//还回连接
try {
conn.close();//这个方法已经被改了(用代理来改的)
} catch (SQLException e) {
e.printStackTrace();
}finally{
conn = null;
}
}
}
}
}