在生产开发中,一个处理方法可能会连接多个数据库,在oracle处理中,有以下几种方式:
1、如果这几个用户在同一个实例中,可以采用授权的方式,比如grant select t1 to test2
,把查询t1的权限赋给用户test2。这样只需要连一个数据库,在查询时加入schema即可
2、如果这几个用户不在同一个实例中,可以建立数据链路,并建立对应的同义词,相当于查询本身的数据表。
上述两种方式都可以实现一个数据库连接,查询别的库的表,不过都有缺点,缺点就是当前的系统不独立,数据连接这些东西耦合到程序中了,如果出现数据库迁移,需要重设权限、数据链路、同义词等等,这后续都是一个非常麻烦的事情。
基于以上问题,可以建立一个多数据源工具,通过这个来连接多个数据库,如果出现数据库迁移,只需要改迁移后的数据库配置即可。
添加依赖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>
数据连接池采用druid,数据库这里以mysql作为例子进行实现,日志用的是logback
DBConnect.java核心数据源工具类
public class DBConnect {
private Connection conn = null;
private static DataSource dataSource;//定义数据源
public static Properties dbProps = null;//定义参数配置
public static String dbName;//定义默认的数据库
public static Hashtable<String, DataSource> hmDataSource = new Hashtable<String, DataSource>();//定义多数据源的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;
}
/**
* 构造数据库的连接和访问类
*/
public DBConnect(String dbName) {
initializeDataSource(dbName);
}
/**
* 无参数构造方法,默认找ldtj数据源
*/
public DBConnect() {
initializeDataSource(dbName);
}
private void initializeDataSource(String dbName) {
dataSource = hmDataSource.get(dbName);
if (dataSource == null)// 建立数据库连接
{
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("数据库连接失败");
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("数据库连接失败");
e.printStackTrace();
}
}
hmDataSource.put(dbName, dataSource);
}
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
logger.error("数据库连接失败:" + 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
这句话是默认的数据库配置,DBConnect的构造方法如果不传参数,默认连接tes这个数据库的配置。
连接池的具体实现方式这个类中提供了两种方式,druid
和weblogic
test.dbPool=druid
这句话是说test的连接池采用druid
来实现,如果采用druid
,需要配置druid的各个参数,包括driver、url、username、password、initialSize、maxActive这些参数,如果采用weblogic
,需要配置test.weblogic.poolName=testPool
,其中testPool
是oracle数据源的名称。
如果需要配第二个数据源,直接赋值粘贴test
的参数,修改为自己的值即可,参照test2
的配置
该工具类可以连接多种数据源,比如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()
即可
上述多数据源连接工具,非常稳定,经历过高并发、多线程等生产检验,可以直接用于自己的开发中。