版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33621967/article/details/53086580
前言:
1)数据库连接池的引进是因为多线程导致作为单例的连接器对象为同一个而导致关流,操作连接器对象时均为同一个等问题,从而引进数据库连接池!
2)装饰模式(包装模式的引进:对于程序员而言,进行关流操作时大家普遍习惯使用close()方法实现,所以引进了装饰模式来应承这种习惯!代码中是将back()–将连接对象还回到连接池中通过装饰模式改成了close()方法!)
3)代理模式(代理模式的引进:实际上代理模式的的实现功能和装饰模式是一样的,但是当用装饰模式时,如果实现的接口中抽象方法很多的话,这将是一个繁琐的工作量,所以引进了代理模式来解决这一问题!)
数据库连接池
工具类:(创建连接器对象)
package cn.hncu.pool;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class ConnUtils {
private static List<Connection> pool = new ArrayList<Connection>();
private static final int NUM=3;
static{
Properties p = new Properties();
try {
p.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String name = p.getProperty("username");
String pwd = p.getProperty("password");
Class.forName(driver);
for (int i = 0; i < NUM; i++) {
Connection conn = DriverManager.getConnection(url, name, pwd);
pool.add(conn);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static synchronized Connection getConn() {
if(pool.size()<=0){
System.out.println("池中没有连接了....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConn();
}
return pool.remove(0);
}
public static void back(Connection con){
System.out.println("往池中还回来一个连接..."+con);
pool.add(con);
}
}
实现类:
package cn.hncu.tx;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import cn.hncu.pool.ConnUtils;
import cn.hncu.pubs.ConnFactory;
//※※使用的是多例的连接池ConnUtils
public class TxDemo2 {
public static void main(String[] args) throws Exception {
Connection con = ConnUtils.getConn();
System.out.println("main线程获得一个连接:"+con);
Statement st = con.createStatement();
try {
con.setAutoCommit(false);//SQL: START TRANSACTION; //开启事务
st.execute("INSERT INTO person2 VALUES('P200','赵子龙','1')");
new MyThread2(1).start();
new MyThread2(2).start();
new MyThread2(3).start();
new MyThread2(4).start();
new MyThread2(5).start();
Thread.sleep(1000);
con.commit();
System.out.println("main线程提交一个事务....");
} catch (Exception e) {
con.rollback();
System.out.println("main线程回滚一个事务.....");
}finally{
con.setAutoCommit(true);
ConnUtils.back(con); //con.close();
}
}
}
class MyThread2 extends Thread{
private int num;
public MyThread2(int num){
this.num = num;
}
@Override
public void run() {
Connection con = ConnUtils.getConn();
System.out.println(num+"线程获得一个连接:"+con);
try {
Statement st = con.createStatement();
con.setAutoCommit(false);//SQL: START TRANSACTION; //开启事务
String sql = "INSERT INTO person2 VALUES('P09"+num+"','赵子龙','1')";
if(num==3){
sql = "INSERT INTO person2 VALUES('P09"+num+",'赵子龙','1')";
}else{
Thread.sleep(100);
}
st.execute(sql);
con.commit();
System.out.println(num+"线程提交一个事务....");
} catch (Exception e) {
try {
con.rollback();
System.out.println(num+"线程回滚一个事务.....");
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
con.setAutoCommit(true);
ConnUtils.back(con); //con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
装饰模式(包装模式)
工具类:
package cn.hncu.pool;
import java.io.IOException;
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.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
public class ConnUtils2 {
private static List<Connection> pool = new ArrayList<Connection>();
private static final int NUM=3;
static{
Properties p = new Properties();
try {
p.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String name = p.getProperty("username");
String pwd = p.getProperty("password");
Class.forName(driver);
for (int i = 0; i < NUM; i++) {
Connection conn = DriverManager.getConnection(url, name, pwd);
//更改conn.close()方法
MyConncetion con = new MyConncetion(conn);
pool.add(con);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static synchronized Connection getConn() {
if(pool.size()<=0){
System.out.println("池中没有连接了....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConn();
}
return pool.remove(0);
}
//采用包装模式(装饰模式) 对Connection conn的功能进行增强
//因为要访问ConnUtils2类中的静态变量pool,因此要声明成静态内部类
static class MyConncetion implements Connection{
private Connection conn;
public MyConncetion(Connection conn ){
this.conn = conn;
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return conn.unwrap(iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return conn.isWrapperFor(iface);
}
@Override
public Statement createStatement() throws SQLException {
return conn.createStatement();
}
@Override
public PreparedStatement prepareStatement(String sql)
throws SQLException {
return conn.prepareStatement(sql);
}
@Override
public CallableStatement prepareCall(String sql) throws SQLException {
return conn.prepareCall(sql);
}
@Override
public String nativeSQL(String sql) throws SQLException {
return conn.nativeSQL(sql);
}
@Override
public void setAutoCommit(boolean autoCommit) throws SQLException {
conn.setAutoCommit(autoCommit);
}
@Override
public boolean getAutoCommit() throws SQLException {
return conn.getAutoCommit();
}
@Override
public void commit() throws SQLException {
conn.commit();
}
@Override
public void rollback() throws SQLException {
conn.rollback();
}
//功能增强就是这个地方,,把原来的close动作改成 还到池中
@Override
public void close() throws SQLException {
System.out.println("往池中还回来一个连接..."+this);
pool.add(this);
}
@Override
public boolean isClosed() throws SQLException {
return conn.isClosed();
}
@Override
public DatabaseMetaData getMetaData() throws SQLException {
return conn.getMetaData();
}
@Override
public void setReadOnly(boolean readOnly) throws SQLException {
conn.setReadOnly(readOnly);
}
@Override
public boolean isReadOnly() throws SQLException {
return conn.isReadOnly();
}
@Override
public void setCatalog(String catalog) throws SQLException {
conn.setCatalog(catalog);
}
@Override
public String getCatalog() throws SQLException {
return conn.getCatalog();
}
@Override
public void setTransactionIsolation(int level) throws SQLException {
conn.setTransactionIsolation(level);
}
@Override
public int getTransactionIsolation() throws SQLException {
return conn.getTransactionIsolation();
}
@Override
public SQLWarning getWarnings() throws SQLException {
return conn.getWarnings();
}
@Override
public void clearWarnings() throws SQLException {
conn.clearWarnings();
}
@Override
public Statement createStatement(int resultSetType,
int resultSetConcurrency) throws SQLException {
return conn.createStatement(resultSetType, resultSetConcurrency);
}
@Override
public PreparedStatement prepareStatement(String sql,
int resultSetType, int resultSetConcurrency)
throws SQLException {
return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency) throws SQLException {
return conn.prepareCall(sql, resultSetType, resultSetConcurrency);
}
@Override
public Map<String, Class<?>> getTypeMap() throws SQLException {
return conn.getTypeMap();
}
@Override
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
conn.setTypeMap(map);
}
@Override
public void setHoldability(int holdability) throws SQLException {
conn.setHoldability(holdability);
}
@Override
public int getHoldability() throws SQLException {
return conn.getHoldability();
}
@Override
public Savepoint setSavepoint() throws SQLException {
return conn.setSavepoint();
}
@Override
public Savepoint setSavepoint(String name) throws SQLException {
return conn.setSavepoint(name);
}
@Override
public void rollback(Savepoint savepoint) throws SQLException {
conn.rollback(savepoint);
}
@Override
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
conn.releaseSavepoint(savepoint);
}
@Override
public Statement createStatement(int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public PreparedStatement prepareStatement(String sql,
int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
}
@Override
public PreparedStatement prepareStatement(String sql,
int autoGeneratedKeys) throws SQLException {
return conn.prepareStatement(sql, autoGeneratedKeys);
}
@Override
public PreparedStatement prepareStatement(String sql,
int[] columnIndexes) throws SQLException {
return conn.prepareStatement(sql, columnIndexes);
}
@Override
public PreparedStatement prepareStatement(String sql,
String[] columnNames) throws SQLException {
return conn.prepareStatement(sql, columnNames);
}
@Override
public Clob createClob() throws SQLException {
return conn.createClob();
}
@Override
public Blob createBlob() throws SQLException {
return conn.createBlob();
}
@Override
public NClob createNClob() throws SQLException {
return conn.createNClob();
}
@Override
public SQLXML createSQLXML() throws SQLException {
return conn.createSQLXML();
}
@Override
public boolean isValid(int timeout) throws SQLException {
return conn.isValid(timeout);
}
@Override
public void setClientInfo(String name, String value)
throws SQLClientInfoException {
conn.setClientInfo(name,value);
}
@Override
public void setClientInfo(Properties properties)
throws SQLClientInfoException {
conn.setClientInfo(properties);
}
@Override
public String getClientInfo(String name) throws SQLException {
return conn.getClientInfo(name);
}
@Override
public Properties getClientInfo() throws SQLException {
return conn.getClientInfo();
}
@Override
public Array createArrayOf(String typeName, Object[] elements)
throws SQLException {
return conn.createArrayOf(typeName, elements);
}
@Override
public Struct createStruct(String typeName, Object[] attributes)
throws SQLException {
return conn.createStruct(typeName, attributes);
}
@Override
public void setSchema(String schema) throws SQLException {
conn.setSchema(schema);
}
@Override
public String getSchema() throws SQLException {
return conn.getSchema();
}
@Override
public void abort(Executor executor) throws SQLException {
conn.abort(executor);
}
@Override
public void setNetworkTimeout(Executor executor, int milliseconds)
throws SQLException {
conn.setNetworkTimeout(executor, milliseconds);
}
@Override
public int getNetworkTimeout() throws SQLException {
return conn.getNetworkTimeout();
}
}
}
实现类:
package cn.hncu.tx;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import cn.hncu.pool.ConnUtils2;
//※※使用的是多例的连接池ConnUtils2 ---更改过con.close()方法的版本
public class TxDemo3 {
public static void main(String[] args) throws Exception {
Connection con = ConnUtils2.getConn();
System.out.println("main线程获得一个连接:"+con);
Statement st = con.createStatement();
try {
con.setAutoCommit(false);//SQL: START TRANSACTION; //开启事务
st.execute("INSERT INTO person2 VALUES('P200','赵子龙','1')");
new MyThread3(1).start();
new MyThread3(2).start();
new MyThread3(3).start();
new MyThread3(4).start();
new MyThread3(5).start();
Thread.sleep(1000);
con.commit();
System.out.println("main线程提交一个事务....");
} catch (Exception e) {
con.rollback();
System.out.println("main线程回滚一个事务.....");
}finally{
con.setAutoCommit(true);
con.close(); //※※※※
}
}
}
class MyThread3 extends Thread{
private int num;
public MyThread3(int num){
this.num = num;
}
@Override
public void run() {
Connection con = ConnUtils2.getConn();
System.out.println(num+"线程获得一个连接:"+con);
try {
Statement st = con.createStatement();
con.setAutoCommit(false);//SQL: START TRANSACTION; //开启事务
String sql = "INSERT INTO person2 VALUES('P09"+num+"','赵子龙','1')";
if(num==3){
sql = "INSERT INTO person2 VALUES('P09"+num+",'赵子龙','1')";
}else{
Thread.sleep(100);
}
st.execute(sql);
con.commit();
System.out.println(num+"线程提交一个事务....");
} catch (Exception e) {
try {
con.rollback();
System.out.println(num+"线程回滚一个事务.....");
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
con.setAutoCommit(true);
con.close();//※※※※
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
代理模式
工具类:
package cn.hncu.pool;
import java.io.IOException;
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.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;
public class ConnUtils3 {
private static List<Connection> pool = new ArrayList<Connection>();
private static final int NUM=3;
static{
Properties p = new Properties();
try {
p.load(ClassLoader.getSystemResourceAsStream("jdbc.properties"));
String driver = p.getProperty("driver");
String url = p.getProperty("url");
String name = p.getProperty("username");
String pwd = p.getProperty("password");
Class.forName(driver);
for (int i = 0; i < NUM; i++) {
final Connection conn = DriverManager.getConnection(url, name, pwd);
//用代理模式生成一个增强版的conn对象,把它的close()方法拦截更改掉
Object newObj = Proxy.newProxyInstance(
ConnUtils3.class.getClassLoader(),
new Class[]{Connection.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
if(method.getName().equals("close")){
pool.add((Connection)proxy);
return null;
}
return method.invoke(conn, args);
}
});
pool.add((Connection)newObj);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static synchronized Connection getConn() {
if(pool.size()<=0){
System.out.println("池中没有连接了....");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getConn();
}
return pool.remove(0);
}
}
实现类:
package cn.hncu.tx;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import cn.hncu.pool.ConnUtils3;
//※※使用的是多例的连接池ConnUtils2 ---更改过con.close()方法的版本
public class TxDemo4 {
public static void main(String[] args) throws Exception {
Connection con = ConnUtils3.getConn();
System.out.println("main线程获得一个连接:"+con);
Statement st = con.createStatement();
try {
con.setAutoCommit(false);//SQL: START TRANSACTION; //开启事务
st.execute("INSERT INTO person2 VALUES('P200','赵子龙','1')");
new MyThread4(1).start();
new MyThread4(2).start();
new MyThread4(3).start();
new MyThread4(4).start();
new MyThread4(5).start();
Thread.sleep(1000);
con.commit();
System.out.println("main线程提交一个事务....");
} catch (Exception e) {
con.rollback();
System.out.println("main线程回滚一个事务.....");
}finally{
con.setAutoCommit(true);
con.close(); //※※※※
}
}
}
class MyThread4 extends Thread{
private int num;
public MyThread4(int num){
this.num = num;
}
@Override
public void run() {
Connection con = ConnUtils3.getConn();
System.out.println(num+"线程获得一个连接:"+con);
try {
Statement st = con.createStatement();
con.setAutoCommit(false);//SQL: START TRANSACTION; //开启事务
String sql = "INSERT INTO person2 VALUES('P09"+num+"','赵子龙','1')";
if(num==3){
sql = "INSERT INTO person2 VALUES('P09"+num+",'赵子龙','1')";
}else{
Thread.sleep(100);
}
st.execute(sql);
con.commit();
System.out.println(num+"线程提交一个事务....");
} catch (Exception e) {
try {
con.rollback();
System.out.println(num+"线程回滚一个事务.....");
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally{
try {
con.setAutoCommit(true);
con.close();//※※※※
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
代理模式中需要用到的类 Proxy: