今天企业应用环境中一般情况下要面对不止一个或一类数据库;另一方面不同时期的不同种类的数据库形成一个个的荒岛;在java中,技术潮流倾向于不是直接操作数据库记录,而是通过中间层的数据库对象持久化处理达到OO的目的。无论那一种,都要求比较容易地面对多个数据库连接。多个数据库连接比较为人所熟悉的是微软的ODBC数据源设置,除了没有实现中间层持久化外,ODBC其实比JDBC要全面也更容易处理。ConnectionManager是一个通过 XML设置的,类似于ODBC数据源设置的东西,通过定义dao.Connection对象,程序可以按需要以:
java.sql.Connection conn
=ConnectionManager.getConnection(${connectionname});
得到所需要的连接,从而简化了在多个数据库环境下的编辑工作。
现在项目开发者面临的常常是多个数据库的应用,历史的和不同部门的,有CS后台的也有BS前台的。各个数据库的数据必须融汇到同一个业务逻辑中,否则就成为一个个低价值的数据孤岛。应对这种需求,目前使用了两种技术,一是数据对象化技术,实质就是在数据层和应用逻辑层中间插入一个持久对象化层,通过程序或容器使数据对象与数据记录相一致,而应用逻辑直接访问数据对象而不是数据库记录;二是通过使用全局目录调动使用多个数据库供数据对象化管理层使用。无论是 EJB ENTITy,还是Hibernate,抑或是我处已写的Hanva Processor都是这种思路的一种体现。
并不总是需要采用EJB才能管理多个数据源,何况大部分项目中采用EJB带的是更高的成本和性能的更低效,开发工作更复杂化,甚至只是碰运气地填代码再发布不行再填代码再碰运气,(我本人很讨厌这种开发感觉,所以搞了一个Hanva的小项目,除非客户指定EJB了)。不过EJB容器中管理多个数据源的方式还是很值得学习的。大部分情况下,它是通过初始化后的数据源对象,象连接池,注册进JNDI SPI;然后通过java.naming.Context.lookup()这个全局名称(在JVM范围内)。我的做法是由写一个 ConnectionManager,它由一个xml文件定义多个数据库连接相关的参数,在ConnectionManager初始化时读入内存。使用时然后通过调用ConnectionManager的静态方法getConnection (String connectionname),就可以得到指定数据库连接。由于实际上操作数据库连接的都是Processor和Lister两个类,这样,要保证连接资源的释放也是很有把握的。依靠这个方法,就可以在轻型的应用中都可以搞妥多数据库,使用数据对象化方式进行开发了。
connections.xml定义:
connection-set供ConnectionManager使用,可以按需要取用不定的多个连接定义,代码完全不变。从而适应多数据库的使用环境;
]]
uri="jdbc:oracle:thin:@127.0.0.1:1521:dkt0" username="dcon" password="girlfriend" /
uri="jdbc:oracle:thin:@127.0.0.1:1521:dkt0" username="erso" password="abc" /
uri="jdbc:oracle:thin:@127.0.0.1:1521:dkt0" username="eef" password="qwewer" /
uri="jdbc:oracle:thin:@127.0.0.1:1521:dkt0" username="system" password="manager" /
ConnectionManager方法:
public class ConnectionManager{
private static LOGGER logger =(LOGGER)Loger.getLogger(Constants.LOGGER_DAIFU_KEY);
public static synchronized java.sql.Connection getConnection() throws java.sql.SQLException{
String name =Repository.getInstance().getConn();
return getConnection(name);
}
public static synchronized java.sql.Connection getConnection(String name) throws java.sql.SQLException{
if(Repository.getInstance()==null){
logger.error("the repository for dao operation has not been initialized");
return null;
}
dao.Connection conn =Repository.getInstance().getConnection(name);
String dri =conn.getDriver();
java.sql.Connection cn =null;
try{
if(dri.equalsIgnoreCase("datasource")){
javax.naming.Context initCtx = new javax.naming.InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource)initCtx.lookup(conn.getUri());
cn
= ds.getConnection();
}
else{
Class.forName(dri);//no newInstance();only get class
cn = java.sql.DriverManager.getConnection(conn.getUri(),conn.getUsername(),conn.getPassword());
}
}catch(Exception ex){
String msg ="ConnectionManager.class,conname:="+name+";dri:="+dri+";cn:="+cn+";msg:="+ex.getMessage();
logger.error(msg,ConnectionManager.class);
throw new java.sql.SQLException(msg);
}
return cn;
}
public static synchronized java.sql.Connection getConnection(dao.Connection conn) throws java.sql.SQLException{
if(conn==null){
System.out.println("the dao.Connection to getConnection is null;");
return null;
}
String dri =conn.getDriver();
java.sql.Connection cn =null;
try{
if(dri.equalsIgnoreCase("datasource")){
javax.naming.Context initCtx = new javax.naming.InitialContext();
javax.sql.DataSource ds = (javax.sql.DataSource)initCtx.lookup(conn.getUri());
cn
= ds.getConnection();
}
else{
Class.forName(dri);//no newInstance();only get class
cn = java.sql.DriverManager.getConnection(conn.getUri(),conn.getUsername(),conn.getPassword());
}
}catch(Exception ex){
String msg ="dri:="+dri+";cn:="+cn+";msg:="+ex.getMessage();
logger.error(msg,ConnectionManager.class);
throw new java.sql.SQLException(msg);
}
return cn;
}
public static void main(String[] args) throws Exception{
if(args==null || args.length<2){
System.out.println(" Please input the xml and conn''s name");
return;
}
Repository.parse(args[0]);
java.sql.Connection conn =getConnection(args[1]);
System.out.println(conn);
}
}
调用时只需要
java.sql.Connection conn =ConnectionManager.getConnection("connn");
就可以得到指定方式的数据库连接。