数据库连接池
当用户使用完Connection,调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。
db.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day16
username=root
password=lcp8090
JdbcPool.java
package cn.lcp.demo;
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.Array;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.NClob;
import java.sql.PreparedStatement;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.sql.DataSource;
public class JdbcPool implements DataSource {
// 用集合保存一批连接。
private static LinkedList<Connection> list = new LinkedList<Connection>();
// 静态代码块,向数据库要连接
static {
try {
InputStream in = JdbcPool.class.getClassLoader()
.getResourceAsStream("db.properties");
Properties prop = new Properties();
prop.load(in);
// 获取驱动等信息
String driver = prop.getProperty("driver");
String url = prop.getProperty("url");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
// 装载驱动
Class.forName(driver);
// 向数据库要多少个连接
for (int i = 0; i < 10; i++) {
// 要到一个连接
Connection conn = DriverManager.getConnection(url, username,
password);
System.out.println("获取到了链接" + conn);
// 把链接到集合里面去了
list.add(conn);
}
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
// 从池里面获取连接
/*
* 1.写一个子类,覆盖close方法--若里面封装有信息,就不要使用此方法
* 2、写一个connection的包装类,增强close方法
* 3、用动态代理,返回一个代理对象出去,拦截close方法的调用,对close进行增强
*/
@Override
public Connection getConnection() throws SQLException {
// proxyConnection.commit() proxyConnection.rollback
if (list.size() > 0) {
//动态设计模式
final Connection conn = list.removeFirst(); // myconnection.commit
System.out.println("池大小是" + list.size());
//Proxy创建一个动态代理对象
return (Connection) Proxy.newProxyInstance(JdbcPool.class
.getClassLoader(), conn.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
if (!method.getName().equals("close")) {
return method.invoke(conn, args);
} else {
list.add(conn);
System.out.println(conn + "被还给池了!!");
System.out.println("池大小为" + list.size());
return null;
}
}
});
} else {
throw new RuntimeException("对不起,数据库忙");
}
}
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 arg0) throws SQLException {
// TODO Auto-generated method stub
}
public void setLoginTimeout(int arg0) throws SQLException {
// TODO Auto-generated method stub
}
@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;
}
}
/*
用包装设计模式对某个对象进行增强
1.写一个类,实现与被增强对象(mysql的connection)相同的接口
2、定义一个变量,指向被增强对象
3、定义一个构造方法,接收被增强对象
4、覆盖想增强的方法
5、对于不想增强的方法,直接调用被增强对象的方法
Connection的包装类
*/
//包装设计模式
class MyConnection implements Connection{
private Connection conn; //记住被增强的对象
private List pool;//记住数据库连接池
//构造函数接受Connection
public MyConnection(Connection conn,List pool){
this.conn = conn;
this.pool = pool; //得到那个数据库连接池
}
//调用自己写的close
public void close() throws SQLException {
pool.add(conn); //把增强的数据还到连接池里面去
}
public void clearWarnings() throws SQLException {
this.conn.clearWarnings(); //对于不想增强的方法,直接调用被增强对象的方法
}
public void commit() throws SQLException {
this.conn.commit();
}
public Statement createStatement() throws SQLException {
return this.conn.createStatement();
}
public Statement createStatement(int resultSetType, int resultSetConcurrency)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Statement createStatement(int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public boolean getAutoCommit() throws SQLException {
// TODO Auto-generated method stub
return false;
}
public String getCatalog() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public int getHoldability() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
public DatabaseMetaData getMetaData() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public int getTransactionIsolation() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
public Map<String, Class<?>> getTypeMap() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public SQLWarning getWarnings() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public boolean isClosed() throws SQLException {
// TODO Auto-generated method stub
return false;
}
public boolean isReadOnly() throws SQLException {
// TODO Auto-generated method stub
return false;
}
public String nativeSQL(String sql) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public CallableStatement prepareCall(String sql) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PreparedStatement prepareStatement(String sql) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PreparedStatement prepareStatement(String sql, String[] columnNames)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
// TODO Auto-generated method stub
}
public void rollback() throws SQLException {
// TODO Auto-generated method stub
}
public void rollback(Savepoint savepoint) throws SQLException {
// TODO Auto-generated method stub
}
public void setAutoCommit(boolean autoCommit) throws SQLException {
// TODO Auto-generated method stub
}
public void setCatalog(String catalog) throws SQLException {
// TODO Auto-generated method stub
}
public void setHoldability(int holdability) throws SQLException {
// TODO Auto-generated method stub
}
public void setReadOnly(boolean readOnly) throws SQLException {
// TODO Auto-generated method stub
}
public Savepoint setSavepoint() throws SQLException {
// TODO Auto-generated method stub
return null;
}
public Savepoint setSavepoint(String name) throws SQLException {
// TODO Auto-generated method stub
return null;
}
public void setTransactionIsolation(int level) throws SQLException {
// TODO Auto-generated method stub
}
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
// TODO Auto-generated method stub
}
@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 Clob createClob() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Blob createBlob() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public NClob createNClob() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public SQLXML createSQLXML() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isValid(int timeout) throws SQLException {
// TODO Auto-generated method stub
return false;
}
@Override
public void setClientInfo(String name, String value)
throws SQLClientInfoException {
// TODO Auto-generated method stub
}
@Override
public void setClientInfo(Properties properties)
throws SQLClientInfoException {
// TODO Auto-generated method stub
}
@Override
public String getClientInfo(String name) throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Properties getClientInfo() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Array createArrayOf(String typeName, Object[] elements)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public Struct createStruct(String typeName, Object[] attributes)
throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public void setSchema(String schema) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public String getSchema() throws SQLException {
// TODO Auto-generated method stub
return null;
}
@Override
public void abort(Executor executor) throws SQLException {
// TODO Auto-generated method stub
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds)
throws SQLException {
// TODO Auto-generated method stub
}
@Override
public int getNetworkTimeout() throws SQLException {
// TODO Auto-generated method stub
return 0;
}
}
JdbcUtils.java
package cn.lcp.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import cn.lcp.demo.JdbcPool;
public class JdbcUtils {
private static JdbcPool pool = new JdbcPool();
public static Connection getConnection() throws SQLException{
return pool.getConnection();
}
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close();
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
}
if(conn!=null){
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
demo.java
package cn.lcp.demo;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import cn.lcp.utils.JdbcUtils;
//模拟转账
public class demo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
Savepoint sp = null;
try {
conn = JdbcUtils.getConnection();
// 执行多条sql语句,开启事务
conn.setAutoCommit(false); // start transaction
String sql1 = "update account set money=money-100 where name=‘aaa‘";
// 预编译sql语句
st = conn.prepareStatement(sql1);
st.executeUpdate();
//设置事务回滚点
sp = conn.setSavepoint();
String sql2 = "update account set money=money+100 where name=‘bbb‘";
st = conn.prepareStatement(sql2);
st.executeUpdate();
int i = 10 / 0; //这里出现异常,到catch里面执行回滚
String sql3 = "update account set money=money+100 where name=‘ccc‘";
st = conn.prepareStatement(sql3);
st.executeUpdate();
//提交事务
conn.commit();
System.out.println("成功!!!"); // log4j
} catch (Exception e) {
try {
conn.rollback(); // 出现异常自动回滚到事务回滚点
conn.commit(); //提交事务---
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.printStackTrace();
} finally {
JdbcUtils.release(conn, st, rs);
}
}
}
proxyConn = (Connection) Proxy.newProxyInstance(this.getClass() .getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() { //此处为内部类,当close方法被调用时将conn还回池中,其它方法直接执行 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getName().equals("close")) { pool.addLast(conn); return null; } return method.invoke(conn, args); } });
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。