本文查閱方法:
一、查閱目錄 —— 查閱本文目錄,肯定想要查閱的目錄標題
二、快捷「查找」 —— 在當前瀏覽器頁面,按鍵 「Ctrl+F」 按鍵組合,開啓瀏覽器的查找功能,
在查找搜索框中 輸入須要查閱的 目錄標題,即可以直接到達 標題內容 的位置。
三、學習小結 —— 文中的學習小結內容,是筆者在學習以後總結出的,開發時可直接參考其進行應用開發的內容, 進一步加快了本文的查閱 速度。(水平有限,僅供參考。)java
本文目錄mysql
學習小結程序員
一、應用程序直接獲取鏈接的缺點(圖解)web
二、使用數據庫鏈接池優化程序性能(圖解)sql
三、可擴展加強某個類方法的功能的三種方式數據庫
四、自定義數據庫鏈接池——基於裝飾設計模式編程
五、數據庫鏈接池核心代碼——基於動態代理技術設計模式
六、開源數據庫鏈接池介紹瀏覽器
七、DBCP數據源tomcat
八、DBCP數據源與應用服務器整合使用—— 配置Tomcat數據源
九、C3P0 數據源
十、JNDI技術簡介
相關學習
JDBC 學習筆記(一)—— 基礎知識 + 分頁技術
連接地址:http://even2012.iteye.com/blog/1886946
JDBC 學習筆記(二)—— 大數據+存儲過程+批處理+事務管理
連接地址:http://even2012.iteye.com/blog/1886950
JDBC 學習筆記(三)—— 數據源(數據庫鏈接池):DBCP數據源、C3P0 數據源以及自定義數據源技術
連接地址:http://even2012.iteye.com/blog/1886953
JDBC 學習筆記(四)—— 自定義JDBC框架+Apache—DBUtils框架+事務管理+操做多表
連接地址:http://even2012.iteye.com/blog/1886956
學習小結
一、應用程序直接獲取鏈接的缺點(圖解)
二、使用數據庫鏈接池優化程序性能(圖解)
三、可擴展加強某個類方法的功能的三種方式
(1) 在實際開發中,發現對象的方法知足不了開發需求時,有三種方式對其進行加強:
(a)建立該類的子類,並覆蓋相應的方法;(較少使用)
(b)使用裝飾(包裝)設計模式;(可使用,但有時書寫的方法太多)
(c)使用動態代理技術。(最優的方式。)
(2) 使用子類覆蓋父類方法的方式來加強功能的弊端:
須要將被加強父類的其餘所需信息也要傳遞到子類中,而在開發中,常常沒法知曉這些所需信息,因此使用子類覆蓋被加強類方法的方式只是用於被加強類的內容較爲簡單的情景。
(3) 使用包裝設計模式加強某個類方法的步驟:
(a) 定義一個類,實現與被加強類相同的接口;
(b) 在類中定義一個變量,記住被加強對象;
(c) 定義一個構造函數,接收被加強對象;
(d) 覆蓋想加強的方法;
(e) 對於不想加強的方法,直接調用目標對象(被加強對象)的方法。
四、自定義數據庫鏈接池——基於裝飾設計模式
編寫鏈接池需實現java.sql.DataSource接口。DataSource接口中定義了兩個重載的getConnection方法:
Connection getConnection()
Connection getConnection(String username, String password)
實現DataSource接口,並實現鏈接池功能的步驟:
(1) 在DataSource構造函數中批量建立與數據庫的鏈接,並把建立的鏈接加入LinkedList對象中。
(2) 實現getConnection方法,讓getConnection方法每次調用時,從LinkedList中取一個Connection返回給用戶。
(3) 當用戶使用完Connection,調用Connection.close()方法時,Collection對象應保證將本身返回到LinkedList中,而不要把conn還給數據庫。
Collection保證將本身返回到LinkedList中是此處編程的難點。
Demo樣例:自定義數據庫鏈接池 (附件:JdbcPool.java)
public class JdbcPool implements DataSource {
private static LinkedList<Connection> list = new LinkedList<Connection>();
private static Properties config = new Properties();
static{
try {
config.load(JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("db.properties"));
// 以配置文件方式 讀取數據庫配置信息。
Class.forName(config.getProperty("driver"));
for(int i=0;i<10;i++){
Connection conn = DriverManager.getConnection(config.getProperty("url"), config.getProperty("username"), config.getProperty("password"));
list.add(conn);
}
} catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
//conn.close() 此方法會將鏈接返回給數據庫,因此不可用,須要自定義加強其功能,將鏈接返回到List集合中。
/* 在實際開發,發現對象的方法知足不了開發需求時,有三種方式對其進行加強
* 1.寫一個connecton子類,覆蓋close方法,加強close方法
* 2.用包裝設計模式
* 3.用動態代理 aop 面向切面編程
*/
public Connection getConnection() throws SQLException {
if(list.size()<=0){
throw new RuntimeException("數據庫忙,請稍會再來!!");
}
Connection conn = list.removeFirst(); //mysqlconnection C
MyConnection my = new MyConnection(conn); 調用自定義連接。
return my; //my-------preparedStatement commit createStatement close
}
// 內部類,固然也可使用外部類
class MyConnection implements Connection{ //1.定義一個類,實現與被加強相同的接口
private Connection conn; //2.在類中定義一個變量,記住被加強對象
public MyConnection(Connection conn){ //3.定義一個構造函數,接收被加強對象
this.conn = conn;
}
public void close(){ //4.覆蓋想加強的方法
list.add(this.conn);
}
//5.對於不想加強的方法,直接調用目標對象(被加強對象)的方法
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();
}
如下省略其餘32個 不想加強的方法。(裝飾模式的缺點,會實現許多不須要加強的方法)
………………
}
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
}
}
五、數據庫鏈接池核心代碼——基於動態代理技術
使用動態代理技術構建鏈接池中的connection
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);
}
}
);
六、開源數據庫鏈接池介紹
如今不少WEB服務器(Weblogic, WebSphere, Tomcat)都提供了DataSource的實現,即鏈接池的實現。一般咱們把DataSource的實現,按其英文含義稱之爲數據源,數據源中都包含了數據庫鏈接池的實現。
也有一些開源組織提供了數據源的獨立實現:
DBCP 數據庫鏈接池 (Tomcat內置)
C3P0 數據庫鏈接池(Spring內置)
實際應用時不須要編寫鏈接數據庫代碼,直接從數據源得到數據庫的鏈接。程序員編程時也應儘可能使用這些數據源的實現,以提高程序的數據庫訪問性能。
備註:簡單地講,使用開源數據源,就是爲了獲取其DataSource對象,而後經過該對象動態的地獲取數據庫鏈接。
七、DBCP數據源
DBCP 是 Apache 軟件基金組織下的開源鏈接池實現,使用DBCP數據源,應用程序應在系統中增長以下兩個 jar 文件:
Commons-dbcp.jar:鏈接池的實現
Commons-pool.jar:鏈接池實現的依賴庫
Tomcat 的鏈接池正是採用該鏈接池來實現的。該數據庫鏈接池既能夠與應用服務器整合使用,也可由應用程序獨立使用。
使用DBCP示例代碼:
static{
InputStream in = JdbcUtil.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
Properties prop = new Properties();
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
dataSource = factory.createDataSource(prop);
}
Demo樣例1:JDBC 數據庫鏈接池 由應用程序獨立使用。
public class JdbcUtils_DBCP {
private static DataSource ds = null;
static{
try{
InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("2013-06-10 11:26");
Properties prop = new Properties();
prop.load(in);
BasicDataSourceFactory factory = new BasicDataSourceFactory();
ds = factory.createDataSource(prop);
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close(); //throw new
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
st = null;
}
if(conn!=null){
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
Demo樣例2: dbcpconfig.properties 文件的內容(也可參見附件)
#鏈接設置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day16
username=root
password=root
#<!-- 初始化鏈接 -->
initialSize=10
#最大鏈接數量
maxActive=50
#<!-- 最大空閒鏈接 -->
maxIdle=20
#<!-- 最小空閒鏈接 -->
minIdle=5
#<!-- 超時等待時間以毫秒爲單位 6000毫秒/1000等於60秒 -->
maxWait=60000
#JDBC驅動創建鏈接時附帶的鏈接屬性屬性的格式必須爲這樣:[屬性名=property;]
#注意:"user" 與 "password" 兩個屬性會被明確地傳遞,所以這裏不須要包含他們。
connectionProperties=useUnicode=true;characterEncoding=utf8
#指定由鏈接池所建立的鏈接的自動提交(auto-commit)狀態。
defaultAutoCommit=true
#driver default 指定由鏈接池所建立的鏈接的只讀(read-only)狀態。
#若是沒有設置該值,則「setReadOnly」方法將不被調用。(某些驅動並不支持只讀模式,如:Informix)
defaultReadOnly=
#driver default 指定由鏈接池所建立的鏈接的事務級別(TransactionIsolation)。
#可用值爲下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_COMMITTED
八、DBCP數據源與應用服務器整合使用—— 配置Tomcat數據源
查看Tomcat文檔(Tomcat-->TomcatDocument-->JNDI Resources-->定位到JDBC Data Sources),示例代碼:
<Context>
<Resource name="jdbc/datasource" auth="Container" type="javax.sql.DataSource"
username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jdbc" maxActive="8" maxIdle="4" />
<Resource name="jdbc/EmployeeDB " auth="Container" type="javax.sql.DataSource"
username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/jdbc" maxActive="8" maxIdle="4" />
</Context>
放置位置:在MyEclipse中,在目錄/META-INF/下建立文件context.xml,將上述內容粘貼其中(注:不要寫XML文件的指令頭句)。該文件將被髮布到Tomcat服務器的conf\Catalina\localhost目錄中,並以工程名稱 命名該文件。
下面是調用JNDI,獲取存儲在JNDI容器中的資源的固定格式代碼(有關JNDI的知識,參見下一章節):
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
dataSource = (DataSource)envCtx.lookup("jdbc/datasource");
特別提醒:此種配置下,驅動jar文件需放置在tomcat的lib下
能夠建立工具類JDBCUtils,java來封裝上面獲取鏈接的代碼。
Demo樣例: 封裝JNDI調用DataSource 獲取鏈接的代碼。
public class JdbcUtils_Tomcat {
private static DataSource ds;
static {
try {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
}
九、C3P0 數據源
所需jar包:
c3p0-0.9.2-pre1.jar
mchange-commons-0.2.jar
c3p0-oracle-thin-extras-0.9.2-pre1.jar(注:鏈接oracle數據庫時才導入,不然不用導入。)
(1) 使用獨立程序編碼的方式配置c3p0數據源(有關數據庫的鏈接信息會被寫入代碼中,不夠優雅)
步驟:一、導入jar包:
二、編碼調用。
Demo:編碼調用c3p0數據源獲取鏈接。
ComboPooledDataSource ds=new ComboPooledDataSource();
ds.setDriverClass("com.mysql.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc1");
ds.setUser("root");
ds.setPassword("root");
ds.setMaxPoolSize(40);
ds.setMinPoolSize(10);
ds.setInitialPoolSize(30);
Connection conn=ds.getConnection();
其餘數據庫的操做
………
(2) 使用配置文件的方式配置c3p0數據源
(a) 配置文件名稱:c3p0-config.xml (必須準確使用該名稱)
(b) 配置文件放置位置:src路徑下或者是web-inf/classes均可以(都同樣)。
(c) 配置文件名稱:c3p0-config.xml 的內容:
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config> <!-- 默認數據庫鏈接池配置信息-->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<!-- 第二個數據庫鏈接池配置信息-->
<named-config name="flx"> <!--自定義數據源鏈接信息,好比能夠分別書寫 mysql 和 oracle 兩個鏈接信息,以方便 換數據庫。 注:此處對應調用代碼中的「鏈接信息名」 -->
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property>
<property name="user">root</property>
<property name="password">root</property>
<property name="acquireIncrement">5</property>
<property name="initialPoolSize">10</property>
<property name="minPoolSize">5</property>
<property name="maxPoolSize">20</property>
</named-config>
</c3p0-config>
(d) 在頁面的調用代碼:ComboPooledDataSource ds =new ComboPooledDataSource(鏈接信息名);
備註:(a)此處對應 c3p0-config.xml 文件中 <named-config name="flx"> 元素——指定名稱的數據源。
(b)數據源名稱不寫,則自動在類路徑下搜索並使用 「默認數據源」;
(c)若書寫名稱,一樣會搜索並調用指定名稱的數據源;
Demo樣例:配置文件方式配置c3p0數據源的調用代碼 。
public class JdbcUtils_C3P0 {
private static ComboPooledDataSource ds = null;
static{
try{
ds = new ComboPooledDataSource(); //沒指定數據源名稱,則使用默認數據源
}catch (Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static Connection getConnection() throws SQLException{
return ds.getConnection();
}
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs!=null){
try{
rs.close(); //throw new
}catch (Exception e) {
e.printStackTrace();
}
rs = null;
}
if(st!=null){
try{
st.close();
}catch (Exception e) {
e.printStackTrace();
}
st = null;
}
if(conn!=null){
try{
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
}
十、JNDI技術簡介
JNDI(Java Naming and Directory Interface),Java命名和目錄接口,它對應於J2SE中的javax.naming包,
這套API的主要做用在於:它能夠把Java對象放在一個容器中(JNDI容器),併爲容器中的java對象取一個名稱,之後程序想得到Java對象,只需經過名稱檢索便可。
其核心API爲Context,它表明JNDI容器,其lookup方法爲檢索容器中對應名稱的對象。
此部份內容簡單瞭解,會用其調用Tomcat內置的DBCP數據源便可。
敬請評論(1)若您以爲本文 有用處 —— 請留言評論,以堅決其餘 IT童鞋 閱讀本文的信心。(2)若您以爲本文 沒用處 —— 請留言評論,筆者將會改進不足,以便爲你們整理更加好用的筆記。