詳解Java動(dòng)態(tài)加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)
問(wèn)題背景
在同一套系統(tǒng)中,要支持連接訪問(wèn)各種流行的數(shù)據(jù)庫(kù),以及同一數(shù)據(jù)庫(kù)的不同版本,例如,oracle9i、oracle10g、oracle11g、oracle12c、sqlserver2000、sqlserver2005、sqlserver2008、sqlserver2012等,其中就會(huì)碰到一些問(wèn)題,就是不同的數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)驅(qū)動(dòng)肯定不同,對(duì)于這個(gè)問(wèn)題到好解決,只需要將相應(yīng)的驅(qū)動(dòng)加入即可;然而對(duì)于同種數(shù)據(jù)庫(kù),不同版本時(shí),而且不同版本的數(shù)據(jù)庫(kù)驅(qū)動(dòng)不僅不兼容,同時(shí)存在還會(huì)出現(xiàn)沖突,例如,能滿足sqlserver2000的驅(qū)動(dòng),就不能滿足sqlserver2012,而能滿足sqlserver2012的驅(qū)動(dòng),就不能滿足sqlserver2000。對(duì)于這種問(wèn)題,面前能想到的解決方案就是動(dòng)態(tài)加載數(shù)據(jù)庫(kù)驅(qū)動(dòng),當(dāng)用到某種數(shù)據(jù)庫(kù)時(shí),就加載其對(duì)應(yīng)的數(shù)據(jù)庫(kù)驅(qū)動(dòng)。
代碼實(shí)現(xiàn)
在此只例出核心代碼,就是動(dòng)態(tài)加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)的類,只是此處暫時(shí)沒(méi)有考慮到數(shù)據(jù)庫(kù)連接池的問(wèn)題,當(dāng)選擇動(dòng)態(tài)加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)時(shí),數(shù)據(jù)庫(kù)連接池需要自己實(shí)現(xiàn),對(duì)于數(shù)據(jù)庫(kù)池的實(shí)現(xiàn),后續(xù)會(huì)出一篇文章專門講解。
DynamicLoaderService
package com.tongtongxue.dynamic.service.impl;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Service;
import com.tongtongxue.dynamic.model.DataSourceInfo;
import com.tongtongxue.dynamic.service.IDynamicLoaderService;
/**
* 動(dòng)態(tài)加載JDBC數(shù)據(jù)庫(kù)驅(qū)動(dòng)服務(wù)類
*
* @author lzj
*
*/
@Service
public class DynamicLoaderService implements IDynamicLoaderService {
// 保存數(shù)據(jù)庫(kù)連接信息
private Map>String, DataSourceInfo< dataSourceInfos = null;
// 保存數(shù)據(jù)庫(kù)相應(yīng)驅(qū)動(dòng)JAR的路徑
private Map>String, String< paths = null;
// 緩存對(duì)應(yīng)的Driver對(duì)象
private Map>String, Driver< drivers = null;
private URLClassLoader classLoader;
/**
* 初始化方法
*
* @throws Exception
*/
@PostConstruct
public void init() throws Exception {
dataSourceInfos = new HashMap>String, DataSourceInfo<();
// 此處只已oracle9和oracle12為例,其它數(shù)據(jù)庫(kù)信息同理的方式增加即可
DataSourceInfo oracle9Info = new DataSourceInfo();
oracle9Info.setDriver("oracle.jdbc.driver.OracleDriver");
oracle9Info.setUrl("jdbc:oracle:thin:@192.168.0.101:1521:ORACLE");
oracle9Info.setUsername("system");
oracle9Info.setPassword("system");
dataSourceInfos.put("oracle9", oracle9Info);
DataSourceInfo oracle12Info = new DataSourceInfo();
oracle12Info.setDriver("oracle.jdbc.driver.OracleDriver");
oracle12Info.setUrl("jdbc:oracle:thin:@192.168.0.102:1521:orcl");
oracle12Info.setUsername("system");
oracle12Info.setPassword("system");
dataSourceInfos.put("oracle12", oracle12Info);
// 將數(shù)據(jù)庫(kù)對(duì)應(yīng)驅(qū)動(dòng)jar放置容器中
paths = new HashMap>String, String<();
paths.put("oracle9", "/driver/ojdbc14.jar");
paths.put("oracle12", "/driver/ojdbc7.jar");
// 初始化drivers
drivers = new HashMap>String, Driver<();
}
@Override
public Connection getConnection(String dbType) throws Exception {
Connection conn = null;
Driver driver = drivers.get(dbType);
DataSourceInfo dataSourceInfo = dataSourceInfos.get(dbType);
if (driver == null) {
URL jarUrl = this.getClass().getResource(paths.get(dbType));
classLoader = new URLClassLoader(new URL[]{jarUrl});
Class>?< driverClass = classLoader.loadClass(dataSourceInfo.getDriver());
driver = (Driver) driverClass.newInstance();
drivers.put(dbType, driver);
}
// 注冊(cè)驅(qū)動(dòng)
DriverManager.registerDriver(driver);
Properties properties = new Properties();
properties.put("user", dataSourceInfo.getUsername());
properties.put("password", dataSourceInfo.getPassword());
conn = DriverManager.getConnection(dataSourceInfo.getUrl(), properties);
// 卸載驅(qū)動(dòng)
DriverManager.deregisterDriver(driver);
return conn;
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Java動(dòng)態(tài)加載類示例詳解
- java 利用java反射機(jī)制動(dòng)態(tài)加載類的簡(jiǎn)單實(shí)現(xiàn)
- java實(shí)現(xiàn)動(dòng)態(tài)編譯并動(dòng)態(tài)加載
- java動(dòng)態(tài)加載插件化編程詳解
- Java 動(dòng)態(tài)加載jar和class文件實(shí)例解析
- java 動(dòng)態(tài)加載的實(shí)現(xiàn)代碼
- Java反射之靜態(tài)加載和動(dòng)態(tài)加載的簡(jiǎn)單實(shí)例
- Java窗體動(dòng)態(tài)加載磁盤文件的實(shí)現(xiàn)方法
- 詳解Java類動(dòng)態(tài)加載和熱替換
相關(guān)文章
Mybatis使用@Select注解sql中使用in問(wèn)題
這篇文章主要介紹了Mybatis使用@Select注解sql中使用in問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
SpringBoot工程打包后執(zhí)行Java?-Jar就能啟動(dòng)的步驟原理
這篇文章主要介紹了SpringBoot工程打包后為何執(zhí)行Java?-Jar就能啟動(dòng),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05
SpringBoot 自動(dòng)掃描第三方包及spring.factories失效的問(wèn)題解決
這篇文章主要介紹了SpringBoot 自動(dòng)掃描第三方包及spring.factories失效的問(wèn)題,本文給大家分享最新解決方法,需要的朋友可以參考下2023-05-05
淺談Java變量賦值運(yùn)算符及相關(guān)實(shí)例
這篇文章主要介紹了Java賦值運(yùn)算符的一些知識(shí),需要的朋友可以參考下。2017-09-09
java中volatile關(guān)鍵字的作用與實(shí)例代碼
這篇文章主要給大家介紹了關(guān)于java中volatile關(guān)鍵字的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
Java中的clone()和Cloneable接口實(shí)例
這篇文章主要介紹了Java中的clone()和Cloneable接口實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Spring Boot Jar 文件能直接運(yùn)行的操作方法
本文將深入探討 Spring Boot 的打包過(guò)程及其運(yùn)行原理,揭示其 JAR 文件如何巧妙地集成依賴項(xiàng)、嵌入 Web 容器并實(shí)現(xiàn)自動(dòng)配置,感興趣的朋友跟隨小編一起看看吧2024-12-12
SpringSecurity 測(cè)試實(shí)戰(zhàn)
這篇文章主要介紹了SpringSecurity 測(cè)試實(shí)戰(zhàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
Spring如何按業(yè)務(wù)模塊輸出日志到不同的文件詳解
最近做項(xiàng)目時(shí)有一個(gè)記錄操作日志的需求,比如某個(gè)用戶進(jìn)行了查詢、刪除、修改等操作,下面這篇文章主要給大家介紹了關(guān)于Spring如何按業(yè)務(wù)模塊輸出日志到不同文件的相關(guān)資料,需要的朋友可以參考下2022-05-05

