TopLink源代码分析 JPA中的如何实现多数据库平台的访问

[问题的由来]

一般来说,通用的商业产品都可以访问多数据库。TopLink也不例外,其中的JPA号称支持上十种数据库平台,而且还可以动态增加。那么具体的技术细节是怎么样呢?怎么实现的呢?

我们来看一看TopLink的源代码是如何实现的。

[源代码分析]

第一步:在登陆访问数据库时,首先执行下面的函数

public void loginAndDetectDatasource() throws DatabaseException {

preConnectDatasource();

Connection conn = null;

try{

conn = (Connection)getReadLogin().connectToDatasource(null);

getLogin().setPlatformClassName(DBPlatformHelper.getDBPlatform(conn.getMetaData().getDatabaseProductName(), getSessionLog()));

}catch (SQLException ex){

DatabaseException dbEx = DatabaseException.errorRetrieveDbMetadataThroughJDBCConnection();

// Typically exception would occur if user did not provide correct connection

// parameters. The root cause of exception should be propogated up

dbEx.initCause(ex);

throw dbEx;

}finally{

if (conn != null){

try{

conn.close();

}catch (SQLException ex){

DatabaseException dbEx = DatabaseException.errorRetrieveDbMetadataThroughJDBCConnection();

// Typically exception would occur if user did not provide correct connection

// parameters. The root cause of exception should be propogated up

dbEx.initCause(ex);

throw dbEx;

}

}

}

connect();

postConnectDatasource();

}

第二步:在上面的函数中,有一个特别重要的函数,大家注意看,叫做DBPlatformHelper.getDBPlatform()

下面我们来看看这个函数到底做了什么?

public static String getDBPlatform(String vendorName, SessionLog logger) {

initializeNameToVendorPlatform(logger);

String detectedDbPlatform = null;

if(vendorName != null) {

detectedDbPlatform = matchVendorNameInProperties(vendorName, _nameToVendorPlatform, logger);

}

if (logger.shouldLog(SessionLog.FINE) ) {

logger.log(SessionLog.FINE, "dbPlaformHelper_detectedVendorPlatform", detectedDbPlatform );

// NOI18N

}

if (detectedDbPlatform == null) {

if(logger.shouldLog(SessionLog.INFO)) {

logger.log(SessionLog.INFO, "dbPlaformHelper_defaultingPlatform", vendorName, DEFAULTPLATFORM); // NOI18N

}

detectedDbPlatform = DEFAULTPLATFORM;

}

return detectedDbPlatform;

}

大家注意看,上面这个函数的第一行是:

initializeNameToVendorPlatform(logger);

这个函数是干什么的?是不是就是访问多数据库强大功能的秘密呢?我们再往下面看。

第三步:秘密原来在这里

private static Properties initializeNameToVendorPlatform(SessionLog logger) {

synchronized(DBPlatformHelper.class) {

if(_nameToVendorPlatform == null) {

_nameToVendorPlatform = new Properties();

try {

loadFromResource(_nameToVendorPlatform, VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME, DBPlatformHelper.class.getClassLoader() );

} catch (IOException e) {

logger.log(SessionLog.WARNING, "dbPlaformHelper_noMappingFound", VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME);

}

}

}

return _nameToVendorPlatform;

}

大家注意看,上面这个函数中,有一个很关键的一行代码

loadFromResource(_nameToVendorPlatform,VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME, DBPlatformHelper.class.getClassLoader() );

这行代码干的事情就是动态的对应到不同的数据库平台。那么到底是怎么做到的呢?

这行代码中有一个变量,名字叫做[VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME]

它的真实面貌如下:

private final static String VENDOR_NAME_TO_PLATFORM_RESOURCE_NAME =PROPERTY_PATH + "VendorNameToPlatformMapping.properties"; //NOI18N

关键问题出现了,原来它是最后找到了一个配置文件,通过它解决不同数据库的访问难题,那么最后我们来看看这个配置文件里面写着什么。

第四步:配置文件

#Property file containing mapping between vendor name and vendor platform

#The key of the property is in form of java regular expression.

#At runtime, vendor name obtained from DatabaseMetaData#getDatabaseProductName()

#is matched against the regular expresion to derive the DatabasePlaform we are

#running against.

SQL\ Anywhere=oracle.toplink.essentials.platform.database.SQLAnyWherePlatform

(?i)oracle.*=oracle.toplink.essentials.platform.database.oracle.OraclePlatform

(?i)(sybase.*)|(adaptive\ server\ enterprise.*)|(SQL\ Server)=oracle.toplink.essentials.platform.database.SybasePlatform

(?i)microsoft.*=oracle.toplink.essentials.platform.database.SQLServerPlatform

#Use JavaDBPlatform as the platform for Derby

(?i).*derby=oracle.toplink.essentials.platform.database.JavaDBPlatform

(?i).*db2.*=oracle.toplink.essentials.platform.database.DB2Platform

(?i)pointbase.*=oracle.toplink.essentials.platform.database.PointBasePlatform

(?i)mysql.*=oracle.toplink.essentials.platform.database.MySQL4Platform

(?i)informix.*=oracle.toplink.essentials.platform.database.InformixPlatform

(?i)postgresql.*=oracle.toplink.essentials.platform.database.PostgreSQLPlatform

(?i).*symfoware.*=oracle.toplink.essentials.platform.database.SymfowarePlatform

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值