在生產(chǎn)開發(fā)中,一個處理方法可能會連接多個數(shù)據(jù)庫谍珊,在oracle處理中治宣,有以下幾種方式:
1、如果這幾個用戶在同一個實例中砌滞,可以采用授權的方式侮邀,比如grant select t1 to test2
,把查詢t1的權限賦給用戶test2贝润。這樣只需要連一個數(shù)據(jù)庫绊茧,在查詢時加入schema即可
2、如果這幾個用戶不在同一個實例中打掘,可以建立數(shù)據(jù)鏈路华畏,并建立對應的同義詞,相當于查詢本身的數(shù)據(jù)表胧卤。
上述兩種方式都可以實現(xiàn)一個數(shù)據(jù)庫連接唯绍,查詢別的庫的表,不過都有缺點枝誊,缺點就是當前的系統(tǒng)不獨立况芒,數(shù)據(jù)連接這些東西耦合到程序中了,如果出現(xiàn)數(shù)據(jù)庫遷移叶撒,需要重設權限绝骚、數(shù)據(jù)鏈路、同義詞等等祠够,這后續(xù)都是一個非常麻煩的事情压汪。
基于以上問題,可以建立一個多數(shù)據(jù)源工具古瓤,通過這個來連接多個數(shù)據(jù)庫止剖,如果出現(xiàn)數(shù)據(jù)庫遷移,只需要改遷移后的數(shù)據(jù)庫配置即可落君。
添加依賴pom.xml
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
數(shù)據(jù)連接池采用druid穿香,數(shù)據(jù)庫這里以mysql作為例子進行實現(xiàn),日志用的是logback
DBConnect.java核心數(shù)據(jù)源工具類
public class DBConnect {
private Connection conn = null;
private static DataSource dataSource;//定義數(shù)據(jù)源
public static Properties dbProps = null;//定義參數(shù)配置
public static String dbName;//定義默認的數(shù)據(jù)庫
public static Hashtable<String, DataSource> hmDataSource = new Hashtable<String, DataSource>();//定義多數(shù)據(jù)源的hashtable
private final static Logger logger = LoggerFactory.getLogger(DBConnect.class);//定義日志
static {
InputStream is = DBConnect.class.getResourceAsStream("/db.properties");
dbProps = new Properties();
try {
dbProps.load(is);
dbName = dbProps.getProperty("defaultDb");
} catch (Exception e) {
logger.error("不能讀取屬性文件. " + "請確保db.properties在CLASSPATH指定的路徑中");
}
}
public static DataSource getdataSource() {
return dataSource;
}
/**
* 構造數(shù)據(jù)庫的連接和訪問類
*/
public DBConnect(String dbName) {
initializeDataSource(dbName);
}
/**
* 無參數(shù)構造方法绎速,默認找ldtj數(shù)據(jù)源
*/
public DBConnect() {
initializeDataSource(dbName);
}
private void initializeDataSource(String dbName) {
dataSource = hmDataSource.get(dbName);
if (dataSource == null)// 建立數(shù)據(jù)庫連接
{
String dbPool = dbProps.getProperty(dbName + ".dbPool");
if (dbPool.equalsIgnoreCase("weblogic")) {
String weblogic_pool = dbProps.getProperty(dbName + ".weblogic.poolName");
Context ctx = null;
Hashtable<Object, Object> ht = new Hashtable<Object, Object>();
ht.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
try {
ctx = new InitialContext(ht);
dataSource = (DataSource) ctx.lookup(weblogic_pool);
} catch (Exception e) {
logger.error("數(shù)據(jù)庫連接失敗");
e.printStackTrace();
}
} else if (dbPool.equalsIgnoreCase("druid")) {
try {
Hashtable<String, String> map = new Hashtable<String, String>();
map.put("driverClassName", dbProps.getProperty(dbName + ".driverClassName"));
map.put("url", dbProps.getProperty(dbName + ".url"));
map.put("username", dbProps.getProperty(dbName + ".username"));
map.put("password", dbProps.getProperty(dbName + ".password"));
map.put("initialSize", dbProps.getProperty(dbName + ".initialSize"));
map.put("maxActive", dbProps.getProperty(dbName + ".maxActive"));
map.put("timeBetweenEvictionRunsMillis", "60000");
map.put("minEvictableIdleTimeMillis", "300000");
map.put("validationQuery", "SELECT 1 FROM DUAL");
map.put("testWhileIdle", "true");
map.put("testOnBorrow", "false");
map.put("testOnReturn", "false");
map.put("removeAbandoned", "true");
map.put("removeAbandonedTimeout", "1800");
map.put("logAbandoned", "true");
DruidDataSourceFactory.createDataSource(map);
dataSource = DruidDataSourceFactory.createDataSource(map);
} catch (Exception e) {
dataSource = null;
logger.error("數(shù)據(jù)庫連接失敗");
e.printStackTrace();
}
}
hmDataSource.put(dbName, dataSource);
}
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
logger.error("數(shù)據(jù)庫連接失敗:" + e.getMessage());
}
}
public Connection getConnection() {
return conn;
}
public void close() {
try {
conn.close();
conn = null;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
db.properties配置文件
#Default DBConnect
defaultDb=test
#test DataBase Pool Config
test.dbPool=druid
test2.dbPool=druid
#test.dbPool=weblogic
#test.weblogic.poolName=testPool
#test Detail Config
test.driverClassName=com.mysql.jdbc.Driver
test.url=jdbc:mysql://127.0.0.1/test
test.username=root
test.password=root
test.initialSize=2
test.maxActive=110
#test2 Detail Config
test2.driverClassName=com.mysql.jdbc.Driver
test2.url=jdbc:mysql://127.0.0.1/test2
test2.username=root
test2.password=root
test2.initialSize=2
test2.maxActive=110
主要說一下配置:
defaultDb=test
這句話是默認的數(shù)據(jù)庫配置皮获,DBConnect的構造方法如果不傳參數(shù),默認連接tes這個數(shù)據(jù)庫的配置纹冤。
連接池的具體實現(xiàn)方式這個類中提供了兩種方式洒宝,druid
和weblogic
test.dbPool=druid
這句話是說test的連接池采用druid
來實現(xiàn)购公,如果采用druid
,需要配置druid的各個參數(shù)雁歌,包括driver宏浩、url、username将宪、password绘闷、initialSize、maxActive這些參數(shù)较坛,如果采用weblogic
印蔗,需要配置test.weblogic.poolName=testPool
,其中testPool
是oracle數(shù)據(jù)源的名稱丑勤。
如果需要配第二個數(shù)據(jù)源华嘹,直接賦值粘貼test
的參數(shù),修改為自己的值即可法竞,參照test2
的配置
該工具類可以連接多種數(shù)據(jù)源耙厚,比如druid和weblogic
測試連多個庫
public static void main(String[] args) {
DBConnect dbc = new DBConnect();
System.out.println(dbc.getConnection());//連接第一個
dbc.close();
DBConnect dbc2 = new DBConnect("test2");
System.out.println(dbc2.getConnection());//連接第二個
dbc2.close();
}
每次獲取Connection
,用完后一定要關閉岔霸,即調用dbc.close()
即可
上述多數(shù)據(jù)源連接工具薛躬,非常穩(wěn)定,經(jīng)歷過高并發(fā)呆细、多線程等生產(chǎn)檢驗型宝,可以直接用于自己的開發(fā)中。