Java創建連接池連接不同數據庫


在一個應用里面,可能涉及到連接多個不同數據庫進行操作,而每次連接寫不同的實現會很麻煩。前面已經會了用JDBC連接數據庫,那么利用反射和工廠模式,可以實現連接不同的數據庫,這樣處理起來將會很方便。同時建造數據庫連接池,處理多個業務數據處理。
 
 

 

那么具體怎么實現呢,下面一起來看一下:
整體結構如下:

 

第一步,先處理連接不同數據庫
1、首先,將數據庫配置信息創建一個公用類:JdbcUrl.java
主數據庫可以用默認的構造方法,如果是連接其他庫,則通過傳遞參數的方式來處理。
數據庫參數有如下幾個:
 
  1 /**
  2  * 數據庫連接配置信息類
  3  * @author Damon
  4  */
  5 public class JdbcUrl
  6 {
  7 
  8     /** 定義數據庫參數 */
  9 
 10     // 數據庫類型
 11     private String DBType;
 12     // 數據庫服務器IP
 13     private String IP;
 14     // 數據庫服務器端口
 15     private String Port;
 16     // 數據庫名稱
 17     private String DBName;
 18     // 用戶名
 19     private String UserName;
 20     // 密碼
 21     private String PassWord;
 22 
 23 
 24     /**
 25      * 默認構造方法,連接默認數據庫
 26      */
 27     public JdbcUrl()
 28     {
 29         // TODO Auto-generated constructor stub
 30         DBType = SysCon.DATABASE_TYPE_MYSQL;
 31         IP = "127.0.0.1";
 32         DBName = "mysql";
 33         Port = "3306";
 34         UserName = "damon";
 35         PassWord = "damon";
 36     }
 37 
 38     /**
 39      * 連接指定數據庫
 40      * @param urlType 傳入連接類型標識
 41      */
 42     public JdbcUrl(String urlType)
 43     {
 44         if ("mysql".equals(urlType))
 45         {
 46             DBType = SysCon.DATABASE_TYPE_MYSQL;
 47             IP = "127.0.0.1";
 48             DBName = "mysql";
 49             Port = "3306";
 50             UserName = "damon";
 51             PassWord = "damon";
 52         }
 53     }
 54 
 55     /**
 56      * 獲取連接句柄
 57      * @return String
 58      */
 59     public String getJdbcUrl()
 60     {
 61         String sUrl = "";
 62 
 63         if (DBType.trim().toUpperCase().equals("MYSQL"))
 64         {
 65             sUrl = "jdbc:mysql://" + IP + ":" + Port + "/" + DBName;
 66         }
 67         else if (DBType.trim().toUpperCase().equals("DB2"))
 68         {
 69             sUrl = "jdbc:db2://" + IP + ":" + Port + "/" + DBName;
 70         }
 71 
 72         else if (DBType.trim().toUpperCase().equals("ORACLE"))
 73         {
 74             sUrl = "jdbc:oracle:thin:@" + IP + ":" + Port + ":" + DBName;
 75         }
 76 
 77         else if (DBType.trim().toUpperCase().equals("SQLSERVER"))
 78         {
 79             sUrl = "jdbc:microsoft:sqlserver://" + IP + ":" + Port + ";databaseName=" + DBName + ";selectMethod=cursor";
 80         }
 81         else if (DBType.trim().toUpperCase().equals("WEBLOGICPOOL"))
 82         {
 83             sUrl = "jdbc:weblogic:pool:" + DBName;
 84         }
 85         else
 86         {
 87             System.out.println("暫無對應數據庫驅動");
 88         }
 89         return sUrl;
 90     }
 91 
 92     // getters and setters
 93 
 94     public String getDBType()
 95     {
 96         return DBType;
 97     }
 98 
 99     public void setDBType(String dBType)
100     {
101         DBType = dBType;
102     }
103 
104     public String getIP()
105     {
106         return IP;
107     }
108 
109     public void setIP(String iP)
110     {
111         IP = iP;
112     }
113 
114     public String getPort()
115     {
116         return Port;
117     }
118 
119     public void setPort(String port)
120     {
121         Port = port;
122     }
123 
124     public String getDBName()
125     {
126         return DBName;
127     }
128 
129     public void setDBName(String dBName)
130     {
131         DBName = dBName;
132     }
133 
134     public String getUserName()
135     {
136         return UserName;
137     }
138 
139     public void setUserName(String userName)
140     {
141         UserName = userName;
142     }
143 
144     public String getPassWord()
145     {
146         return PassWord;
147     }
148 
149     public void setPassWord(String passWord)
150     {
151         PassWord = passWord;
152     }
153 
154 }
View Code

 

2、重寫一個Connection類,實現Connection接口的方法,同時連接數據庫。

參數有已實現的JdbrUrl類,主要新增方法為:createConnection()
根據DBType來對不同數據庫進行處理:加載對應的數據庫,然后獲取數據庫連接。
  1 **
  2  * 數據庫連接類,連接數據庫
  3  * @author Damon
  4  */
  5 public class DBConn implements Connection
  6 {
  7 
  8     // 獲取JdbcUrl信息
  9     private JdbcUrl JUrl;
 10 
 11     // 數據庫連接
 12     private Connection con = null;
 13 
 14     // 連接是否已使用
 15     private boolean bNotInUse;
 16 
 17     private CharArrayWriter m_buf = new CharArrayWriter();
 18 
 19     private PrintWriter m_pw = new PrintWriter(m_buf, true);
 20 
 21     // 默認連接
 22     public DBConn()
 23     {
 24         // TODO Auto-generated constructor stub
 25         this.JUrl = new JdbcUrl();
 26     }
 27 
 28     // 指定數據庫連接
 29     public DBConn(String urlType)
 30     {
 31         this.JUrl = new JdbcUrl(urlType);
 32     }
 33 
 34     // 創建連接
 35     public boolean createConnection()
 36     {
 37 
 38         // 根據數據庫類型加載驅動及連接
 39         try
 40         {
 41             // 連接MySQL數據庫
 42             if (SysCon.DATABASE_TYPE_MYSQL.equals(JUrl.getDBType()))
 43             {
 44                 // 加載數據庫驅動
 45                 Class.forName("com.mysql.jdbc.Driver");
 46 
 47                 // 嘗試連接數據庫
 48                 con = DriverManager.getConnection(JUrl.getJdbcUrl(), JUrl.getUserName(), JUrl.getPassWord());
 49             }
 50             // 其他數據庫類型判斷及處理
 51             // SQLSERVER
 52             else if (SysCon.DATABASE_TYPE_SQLSERVER.equals(JUrl.getDBType()))
 53             {
 54                 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
 55                 con = DriverManager.getConnection(JUrl.getJdbcUrl(), JUrl.getUserName(), JUrl.getPassWord());
 56             }
 57             // DB2
 58             else if (SysCon.DATABASE_TYPE_DB2.equals(JUrl.getDBType()))
 59             {
 60                 Class.forName("com.ibm.db2.jcc.DB2Driver");
 61                 con = DriverManager.getConnection(JUrl.getJdbcUrl(), JUrl.getUserName(), JUrl.getPassWord());
 62             }
 63             // ORACLE
 64             else if (SysCon.DATABASE_TYPE_ORACLE.equals(JUrl.getDBType()))
 65             {
 66                 Class.forName("oracle.jdbc.driver.OracleDriver");
 67                 // 一個是緩存取到的記錄數,一個是設置默認的批量提交數
 68                 Properties props = new Properties();
 69                 props.setProperty("user", JUrl.getUserName());
 70                 props.setProperty("password", JUrl.getPassWord());
 71                 props.setProperty("defaultRowPrefetch", "50");
 72                 props.setProperty("defaultExecuteBatch", "50");
 73                 con = DriverManager.getConnection(JUrl.getJdbcUrl(), props);
 74             }
 75             else
 76             {
 77                 System.out.println("未匹配到數據庫類型!");
 78                 return false;
 79             }
 80 
 81         }
 82         catch (ClassNotFoundException e)
 83         {
 84             // TODO Auto-generated catch block
 85             System.out.println("加載驅動失敗!");
 86             e.printStackTrace();
 87             return false;
 88         }
 89         catch (SQLException e)
 90         {
 91             // TODO Auto-generated catch block
 92             System.out.println("創建連接失敗..." + e.getMessage());
 93             e.printStackTrace();
 94             return false;
 95         }
 96         return true;
 97     }
 98 
 99     protected void setInUse()
100     {
101         /**
102          * Record stack information when each connection is get We reassian
103          * System.err, so Thread.currentThread().dumpStack() can dump stack info
104          * into our class FilterPrintStream.
105          */
106         new Throwable().printStackTrace(m_pw);
107 
108         bNotInUse = false;
109 
110         /**
111          * record lastest access time
112          */
113     }
114 
115     /* 下面都是 實現Connection的方法,返回conn的實現 */
116     public <T> T unwrap(Class<T> iface) throws SQLException
117     {
118         // TODO Auto-generated method stub
119         return con.unwrap(null);
120     }
121 
122     public boolean isWrapperFor(Class<?> iface) throws SQLException
123     {
124         // TODO Auto-generated method stub
125         return false;
126     }
127 
128     public Statement createStatement() throws SQLException
129     {
130         // TODO Auto-generated method stub
131         return con.createStatement();
132     }
133 
134     public PreparedStatement prepareStatement(String sql) throws SQLException
135     {
136         // TODO Auto-generated method stub
137         return con.prepareStatement(sql);
138     }
139 
140     public CallableStatement prepareCall(String sql) throws SQLException
141     {
142         // TODO Auto-generated method stub
143         return con.prepareCall(sql);
144     }
145 
146     public String nativeSQL(String sql) throws SQLException
147     {
148         // TODO Auto-generated method stub
149         return con.nativeSQL(sql);
150     }
151 
152     public void setAutoCommit(boolean autoCommit) throws SQLException
153     {
154         // TODO Auto-generated method stub
155         con.setAutoCommit(autoCommit);
156     }
157 
158     public boolean getAutoCommit() throws SQLException
159     {
160         // TODO Auto-generated method stub
161         return con.getAutoCommit();
162     }
163 
164     public void commit() throws SQLException
165     {
166         // TODO Auto-generated method stub
167         con.commit();
168     }
169 
170     public void rollback() throws SQLException
171     {
172         // TODO Auto-generated method stub
173         con.rollback();
174     }
175 
176     public void close() throws SQLException
177     {
178         // TODO Auto-generated method stub
179         con.close();
180     }
181 
182     public boolean isClosed() throws SQLException
183     {
184         // TODO Auto-generated method stub
185 
186         return con.isClosed();
187     }
188 
189     public DatabaseMetaData getMetaData() throws SQLException
190     {
191         // TODO Auto-generated method stub
192         return con.getMetaData();
193     }
194 
195     public void setReadOnly(boolean readOnly) throws SQLException
196     {
197         // TODO Auto-generated method stub
198         con.setReadOnly(readOnly);
199     }
200 
201     public boolean isReadOnly() throws SQLException
202     {
203         // TODO Auto-generated method stub
204         return con.isReadOnly();
205     }
206 
207     public void setCatalog(String catalog) throws SQLException
208     {
209         // TODO Auto-generated method stub
210         con.setCatalog(catalog);
211     }
212 
213     public String getCatalog() throws SQLException
214     {
215         // TODO Auto-generated method stub
216         return con.getCatalog();
217     }
218 
219     public void setTransactionIsolation(int level) throws SQLException
220     {
221         // TODO Auto-generated method stub
222         con.setTransactionIsolation(level);
223     }
224 
225     public int getTransactionIsolation() throws SQLException
226     {
227         // TODO Auto-generated method stub
228         return con.getTransactionIsolation();
229     }
230 
231     public SQLWarning getWarnings() throws SQLException
232     {
233         // TODO Auto-generated method stub
234         return con.getWarnings();
235     }
236 
237     public void clearWarnings() throws SQLException
238     {
239         // TODO Auto-generated method stub
240         con.clearWarnings();
241     }
242 
243     public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
244     {
245         // TODO Auto-generated method stub
246         return con.createStatement(resultSetType, resultSetConcurrency);
247     }
248 
249     public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
250             throws SQLException
251     {
252         // TODO Auto-generated method stub
253         return con.prepareStatement(sql, resultSetType, resultSetConcurrency);
254     }
255 
256     public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
257     {
258         // TODO Auto-generated method stub
259         return con.prepareCall(sql, resultSetType, resultSetConcurrency);
260     }
261 
262     public Map<String, Class<?>> getTypeMap() throws SQLException
263     {
264         // TODO Auto-generated method stub
265         return con.getTypeMap();
266     }
267 
268     public void setTypeMap(Map<String, Class<?>> map) throws SQLException
269     {
270         // TODO Auto-generated method stub
271         con.setTypeMap(map);
272     }
273 
274     public void setHoldability(int holdability) throws SQLException
275     {
276         // TODO Auto-generated method stub
277         con.setHoldability(holdability);
278     }
279 
280     public int getHoldability() throws SQLException
281     {
282         // TODO Auto-generated method stub
283         return con.getHoldability();
284     }
285 
286     public Savepoint setSavepoint() throws SQLException
287     {
288         // TODO Auto-generated method stub
289         return con.setSavepoint();
290     }
291 
292     public Savepoint setSavepoint(String name) throws SQLException
293     {
294         // TODO Auto-generated method stub
295         return con.setSavepoint(name);
296     }
297 
298     public void rollback(Savepoint savepoint) throws SQLException
299     {
300         // TODO Auto-generated method stub
301         con.rollback(savepoint);
302     }
303 
304     public void releaseSavepoint(Savepoint savepoint) throws SQLException
305     {
306         // TODO Auto-generated method stub
307         con.releaseSavepoint(savepoint);
308     }
309 
310     public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
311             throws SQLException
312     {
313         // TODO Auto-generated method stub
314         return con.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
315     }
316 
317     public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
318             int resultSetHoldability) throws SQLException
319     {
320         // TODO Auto-generated method stub
321         return con.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
322     }
323 
324     public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
325             int resultSetHoldability) throws SQLException
326     {
327         // TODO Auto-generated method stub
328         return null;
329     }
330 
331     public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
332     {
333         // TODO Auto-generated method stub
334         return con.prepareStatement(sql, autoGeneratedKeys);
335     }
336 
337     public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
338     {
339         // TODO Auto-generated method stub
340         return con.prepareStatement(sql, columnIndexes);
341     }
342 
343     public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
344     {
345         // TODO Auto-generated method stub
346         return con.prepareStatement(sql, columnNames);
347     }
348 
349     public Clob createClob() throws SQLException
350     {
351         // TODO Auto-generated method stub
352         return con.createClob();
353     }
354 
355     public Blob createBlob() throws SQLException
356     {
357         // TODO Auto-generated method stub
358         return con.createBlob();
359     }
360 
361     public NClob createNClob() throws SQLException
362     {
363         // TODO Auto-generated method stub
364         return con.createNClob();
365     }
366 
367     public SQLXML createSQLXML() throws SQLException
368     {
369         // TODO Auto-generated method stub
370         return con.createSQLXML();
371     }
372 
373     public boolean isValid(int timeout) throws SQLException
374     {
375         // TODO Auto-generated method stub
376         return con.isValid(timeout);
377     }
378 
379     public void setClientInfo(String name, String value) throws SQLClientInfoException
380     {
381         // TODO Auto-generated method stub
382         con.setClientInfo(name, value);
383     }
384 
385     public void setClientInfo(Properties properties) throws SQLClientInfoException
386     {
387         // TODO Auto-generated method stub
388         con.setClientInfo(properties);
389     }
390 
391     public String getClientInfo(String name) throws SQLException
392     {
393         // TODO Auto-generated method stub
394         return con.getClientInfo(name);
395     }
396 
397     public Properties getClientInfo() throws SQLException
398     {
399         // TODO Auto-generated method stub
400         return con.getClientInfo();
401     }
402 
403     public Array createArrayOf(String typeName, Object[] elements) throws SQLException
404     {
405         // TODO Auto-generated method stub
406         return con.createArrayOf(typeName, elements);
407     }
408 
409     public Struct createStruct(String typeName, Object[] attributes) throws SQLException
410     {
411         // TODO Auto-generated method stub
412         return con.createStruct(typeName, attributes);
413     }
414 
415 }
View Code

 

3、公共的數據庫連接池

數據庫配置和數據庫連接已經搞定,那么可以建一個數據庫連接池來進行數據庫的連接及處理。
主要有2個方法,連接默認數據庫和連接指定的數據庫。
 1 /**
 2      * 獲取默認數據庫連接
 3      * @param uri
 4      * @return
 5      */
 6     public static DBConn getConnection()
 7     {
 8         DBConn dbConn = new DBConn();
 9         if (!dbConn.createConnection())
10         {
11             // 如果創建連接失敗
12             DBSemaphore.unLock();
13             return null;
14         }
15 
16         // 連接成功,設置該連接屬性
17         try
18         {
19             // 特殊處理連接的AutoCommit是否已經被設置
20             dbConn.setAutoCommit(true);
21             dbConn.setInUse();
22             DBSemaphore.unLock();
23             return dbConn;
24         }
25         catch (Exception ex)
26         {
27             ex.printStackTrace();
28             DBSemaphore.unLock();
29             return null;
30         }
31 
32     }
33 
34     /**
35      * 通過URI地址獲取指定數據庫連接
36      * @param uri
37      * @return
38      */
39     public static DBConn getConnection(String uri)
40     {
41         DBConn dbConn = new DBConn(uri);
42         if (!dbConn.createConnection())
43         {
44             // 如果創建連接失敗
45             // DBSemaphore.UnLock();
46             return null;
47         }
48         try
49         {
50             // 特殊處理連接的AutoCommit是否已經被設置
51             dbConn.setAutoCommit(true);
52             // dbConn.setInUse();
53             // DBSemaphore.UnLock();
54             return dbConn;
55         }
56         catch (Exception ex)
57         {
58             ex.printStackTrace();
59             // DBSemaphore.UnLock();
60             return null;
61         }
62 
63     }
View Code

 

可以寫一個測試方式,這也數據庫連接就完成了,通過傳入不同的參數就可以獲取到不同數據庫的連接了。
 
 1     public static void main(String[] args)
 2     {
 3         // 測試連接池
 4 
 5         // 1、連接mysql 數據庫
 6         Connection conn = DBConnPool.getConnection();
 7 
 8         if (conn == null)
 9         {
10             System.out.println("獲取連接失敗!");
11         }
12         else
13         {
14             System.out.println("獲取連接成功");
15         }
16 
17     }
View Code

 

第二步,構建數據庫連接池
前面已經實現連接不同數據庫,那么怎么處理為連接池呢?
數據庫連接池負責分配、管理和釋放數據庫連接,它允許應用程序重復使用一個現有的數據庫連接,而不是再重新建立一個;釋放空閑時間超過最大空閑時間的數據庫連接來避免因為沒有釋放數據庫連接而引起的數據庫連接遺漏。這項技術能明顯提高對數據庫操作的性能。下面我們就來實現數據庫連接池的功能:

 

數據庫連接池的實現思想主要有如下幾個方面:
1、可定義最大和最小的連接數:如果請求小於最小連接數,則直接分配連接,達到最大連接數則新請求等待;
2、用戶在連接數據庫時,不用新建連接,而是直接從連接池中獲取連接,使用完畢后也不用關閉,而是釋放給連接池,供下一個用戶使用;
下面來進行實現:
其實就是實現了一個數據連接數的判斷,最大連接數進行限制,實際的數據庫連接池需結合對應的數據庫連接池組件(比如 WebSphere等中間件),在判斷是否有連接在使用的時候,會涉及到並發,這里需要用到volatile關鍵字。
 
其中,增加了DBsemaphor類,用以處理連接的使用和釋放。
在原有DBConn基礎上,加上是否已使用方法,在獲取連接成功時調用,具體代碼如下:
 
 1 // 連接成功,設置該連接屬性
 2         try
 3         {
 4             // 特殊處理連接的AutoCommit是否已經被設置
 5             dbConn.setAutoCommit(true);
 6             dbConn.setInUse();
 7             DBSemaphore.unLock();
 8             return dbConn;
 9         }
10         catch (Exception ex)
11         {
12             ex.printStackTrace();
13             DBSemaphore.unLock();
14             return null;
15         }
View Code

新增DBSemaphore類屬性及方法如下:

 1 /**
 2  * 數據庫同步對象
 3  * @author Damon
 4  */
 5 public class DBSemaphore
 6 {
 7     private static volatile boolean m_bInUse = false;
 8 
 9     public DBSemaphore()
10     {}
11 
12     /**
13      * 設置"使用標志"。 傳入true表示請求“使用標志”,傳入false表示釋放“使用標志”。
14      * @param bNewValue boolean
15      * @return boolean
16      */
17     protected static synchronized boolean setInUseFlag(boolean bNewValue)
18     {
19         if (bNewValue == true)
20         {
21             // 請求“使用標志”
22             if (m_bInUse == true)
23             {
24                 // “使用標志”已經被占用
25                 return false;
26             }
27             else
28             {
29                 m_bInUse = true;
30                 return true;
31             }
32         }
33         else
34         {
35             // 釋放“使用標志”
36             m_bInUse = false;
37             return true;
38         }
39     }
40 
41     protected static void lock() throws Exception
42     {
43         lock(0);
44     }
45 
46     protected static void lock(int nSeconds) throws Exception
47     {
48         if (nSeconds <= 0)
49         {
50             while (!setInUseFlag(true))
51             {
52                 Thread.sleep(100);
53             }
54         }
55         else
56         {
57             while (!setInUseFlag(true) && nSeconds-- > 0)
58             {
59                 Thread.sleep(100);
60             }
61 
62             if (nSeconds == 0)
63             {
64                 throw new Exception("Lock time out");
65             }
66         }
67     }
68 
69     protected static void unLock()
70     {
71         setInUseFlag(false);
72     }
73 }
View Code

 

到這里,整個配置處理結束了,更多的就需要在實際項目中發揮了~  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM