1.數(shù)據(jù)庫連接池原理眶明?
1.1 什么是數(shù)據(jù)庫連接池?
個人覺得了解一個技術首先要清楚它的出現(xiàn)解決了什么樣的問題 ,扮演怎樣的角色普气。目前數(shù)據(jù)庫直接獲取鏈接有這樣的問題:
用戶每次請求都需要向數(shù)據(jù)庫獲得鏈接盗尸,而數(shù)據(jù)庫創(chuàng)建鏈接通常需要消耗相對較大的資源柑船,創(chuàng)建時間也較長,如果網(wǎng)站一天有10萬訪問量泼各,數(shù)據(jù)庫服務器就需要創(chuàng)建10萬次鏈接鞍时,極大的浪費數(shù)據(jù)庫的資源,并且極易造成數(shù)據(jù)庫服務內存溢出 拓機扣蜻。
如果當你需要鏈接的時候逆巍,有一個庫在你需要可以直接給你提供,那效率將會得到很大的提升莽使。而這個庫就是數(shù)據(jù)庫連接池锐极。
數(shù)據(jù)庫連接池的優(yōu)點:提高數(shù)據(jù)庫鏈接的效率;
1.2 模擬簡單的數(shù)據(jù)庫連接池吮旅?
// 存放鏈接對象的池
private static Listpool = Collections.synchronizedList(new ArrayList());
// 初始化一些鏈接到池中
static{
for (int i = 0; i < 10; i++) {
Connection conn = JDBCUtils.getConn();
pool.add(conn);
}
}
// 從連接池中獲取鏈接
public static Connection getConnection(){
if (pool.size()>0) {
return pool.remove(0);
}else{
throw new RuntimeException("service busy!");
}
}
// 用完之后還回池中
public static void release (Connection conn){
pool.add(conn);
}
1.3編寫標準的數(shù)據(jù)源溪烤?
需要實現(xiàn)javax.sql.datasource
實現(xiàn) getConnection,就可以了庇勃。
public Connection getConnection() throws SQLException {
if (pool.size()>0) {
return pool.remove(0);
}else{
throw new RuntimeException("service busy!");
}
}
編程會遇到的問題檬嘀?
conn.close(); //把鏈接關閉了。? 不應該關閉责嚷,應該放回池中鸳兽。
解決方案:
第一反應是繼承Connection,覆蓋系統(tǒng)的close()方法罕拂。 但是在這里不合適揍异。
會涉及到多個數(shù)據(jù)庫混亂全陨。
1>.裝飾設計模式
裝飾設計模式的步驟:
1.編寫一個類,實現(xiàn)與被裝飾類相同的接口衷掷。目的是使他們有相同的行為辱姨。
2.定義一個實例變量,引用被裝飾對象戚嗅。目的是和原來的老對象進行交接
3.定義構造方法把被裝飾對象注入進來雨涛。
4. 對于不需要改寫的方法,調用被裝飾的對象懦胞。
5.對于要改寫的方法改寫即可替久。
private Connection conn;
private Listpool;
public MyConnection(Connection conn, Listpoo) {
this.conn = conn;
this.pool = pool;
}
// 把connection還會池中
public void close() throws SQLException {
// TODO Auto-generated method stub
pool.add(conn);
}
2>. 默認適配器
編寫一個類,實現(xiàn)與被裝飾類相同的接口躏尉。?
編寫一個類蚯根,繼承上個類,實現(xiàn)要操作的方法 ?-> 避免每次操作都要是實現(xiàn)很多原聲的方法胀糜。
3>. 代理模式(重點)
代理的概念: 自己想要做的事情颅拦,通過外界(具體怎么做到的我不管),然后實現(xiàn)了自己的目的僚纷。
AOP編程技術實現(xiàn)矩距,動態(tài)代理:
基于接口的動態(tài)代理:
前提: 被代理對象的類,至少實現(xiàn)了一個接口怖竭。
基于子類的動態(tài)代理:
借助第三方锥债。CGLIB
public Connection getConnection() throws SQLException {
if (pool.size()>0) {
final Connection conn =? pool.remove(0);
//MyConnection mConn = new MyConnection(conn, pool);
Connection proxyConn = (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())){
//用戶調用的colse還會
return pool.add(conn);
}else{
// 返回對應的方法
return invoke(conn, method, args);
}
}
});
return proxyConn;
}else{
throw new RuntimeException("service busy!");
}
}
2.數(shù)據(jù)庫連接池怎么用?
1> DBCP的使用:
1.是apache的開源組件痊臭。 導入 jar? commons-dbcp-1.4.jar 跟 ?commons-pool-1.5.6.jar
2.添加配置文件
3.編寫一個工具類哮肚。
代碼:
private static DataSource ds;
static{
// 讀取配置文件
Properties props = new Properties();
InputStream in = DBCPUtial.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
try {
props.load(in);
ds=BasicDataSourceFactory.createDataSource(props);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static DataSource getDataSource(){
return ds;
}
public static Connection getConnection(){
try {
return ds.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
2>C3P0的使用:
1. 開源的數(shù)據(jù)庫
2. 拷貝jar包? c3p0-0.9.1.2.jar
3>利用Web服務器管理數(shù)據(jù)元(JNDI)
1. 主流的web服務器都提供數(shù)據(jù)源的實現(xiàn),基本都是配置一下广匙。
2. JNDI: Java Naming and Driectory Inerface;
3.JDBC框架允趟?
3.1.數(shù)據(jù)庫的元信息的獲取鸦致?
數(shù)據(jù)庫或表的定義信息潮剪,或者結果集的一些信息。
rs.getMetaData();
3.2.編寫自己的JDBC框架(約定優(yōu)于編碼)分唾?