IBatis2中提供了3种DataSource的配置:JNDI, Apache DBCP, IBatis自带的SimpleDataSource。但在IBatis3中只提供了两种DataSource: UNPOOLED, POOLED。
如果要实现自定义的DataSource,就需要通过扩展DataSourceFactory。本文就演示一下这个过程。
准备工作:Connection Pool的选择,通过搜索发现目前比较流行的免费数据库连接池主要有3种:Apache DBCP, C3P0, Proxool。
看了一下,Proxool的最新版本是0.9.1(2008-08-23), C3P0的最新版本是0.9.1.2(2007-05-21), DBCP最新版本是1.2.2(2007-04-04)
好像这3个项目都已经挺长时间没有更新了。但是总体评价上C3P0无论从稳定上还是效率上都要好一点。
(具体这3个项目谁更优秀,并不是本文的重点,本文主要是介绍一下如何在IBatis3中自定义数据源)
大致步骤:
1、实现org.apache.ibatis.datasource.DataSourceFactory接口,主要是2个方法
a、public DataSource getDataSource() 如何具体地得到一个数据源
b、public void setProperties(Properties properties) 如何设置数据源的参数属性
2、实现javax.sql.DataSource,这个就是提供给DataSourceFactory的实例
3、在IBatis3中引用新加入的数据源
1. 从代码中可以看出,IBatis3与IBatis2不同,不再通过一个Configuration类来进行数据源属性的设置,而是使用反射机制直接调用数据源的方法来设置参数。
这就要求配置文件中的参数名称必须与数据源类中的方法名匹配.
ProxoolDataSourceFactory.java
package com.xuanwu.ibatis;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.ibatis.datasource.DataSourceException; import org.apache.ibatis.datasource.DataSourceFactory; import org.apache.ibatis.reflection.MetaObject;
/** * fisher 2010-7-14 下午06:18:16 * * Proxool数据源连接池工厂 * * @see http://www.blogjava.net/usherlight/archive/2010/02/01/311493.html * */ public class ProxoolDataSourceFactory implements DataSourceFactory {
private DataSource dataSource;
public ProxoolDataSourceFactory() { dataSource = new ProxoolDataSourceWrap(); }
public DataSource getDataSource() { return dataSource; }
/** * IBatis3与IBatis2不同,不再通过一个Configuration类来进行数据源属性的设置, * 而是使用反射机制直接调用数据源的方法来设置参数。 */ public void setProperties(Properties properties) { Properties driverProperties = new Properties(); MetaObject metaDataSource = MetaObject.forObject(dataSource); for (Object key : properties.keySet()) { String propertyName = (String) key; if (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) { String value = properties.getProperty(propertyName); driverProperties.setProperty(propertyName .substring(DRIVER_PROPERTY_PREFIX_LENGTH), value); } else if (metaDataSource.hasSetter(propertyName)) { String value = (String) properties.get(propertyName); Object convertedValue = convertValue(metaDataSource, propertyName, value); metaDataSource.setValue(propertyName, convertedValue); } else { throw new DataSourceException("Unkown DataSource property: " + propertyName); } } if (driverProperties.size() > 0) { metaDataSource.setValue("driverProperties", driverProperties); } }
@SuppressWarnings("unchecked") private Object convertValue(MetaObject metaDataSource, String propertyName, String value) { Object convertedValue = value; Class targetType = metaDataSource.getSetterType(propertyName); if (targetType == Integer.class || targetType == int.class) { convertedValue = Integer.valueOf(value); } else if (targetType == Long.class || targetType == long.class) { convertedValue = Long.valueOf(value); } else if (targetType == Boolean.class || targetType == boolean.class) { convertedValue = Boolean.valueOf(value); } return convertedValue; }
private static final String DRIVER_PROPERTY_PREFIX = "driver."; private static final int DRIVER_PROPERTY_PREFIX_LENGTH = DRIVER_PROPERTY_PREFIX .length();
}
|
2. 数据源类,其中的一堆setter就是用于设置属性的。
ProxoolDataSourceWrap.java
package com.xuanwu.ibatis;
import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException;
import javax.sql.DataSource;
import org.logicalcobwebs.proxool.ProxoolDataSource;
/** * fisher 2010-7-14 下午06:18:16 * * 数据源配置。配置文件xml上dataSource设置的属性与连接池对应桥梁。 * * @see http://www.blogjava.net/usherlight/archive/2010/02/01/311493.html */ public class ProxoolDataSourceWrap implements DataSource { private ProxoolDataSource dataSource;
public ProxoolDataSourceWrap() { this.dataSource = new ProxoolDataSource(); }
public Connection getConnection() throws SQLException { return dataSource.getConnection(); }
public Connection getConnection(String username, String password) throws SQLException { return dataSource.getConnection(username, password); }
public PrintWriter getLogWriter() throws SQLException { return dataSource.getLogWriter(); }
public int getLoginTimeout() throws SQLException { return dataSource.getLoginTimeout(); }
public void setLogWriter(PrintWriter out) throws SQLException { dataSource.setLogWriter(out); }
public void setLoginTimeout(int seconds) throws SQLException { dataSource.setLoginTimeout(seconds); }
/** 以下setter,对应ibatis-config.xml dataSource下的property **/ //
//
//
//
//
// ...............
//
/** ProxoolDataSource setter源码 **/ // cpd.setAlias(getAlias());
// cpd.setDriver(getDriver());
// cpd.setFatalSqlExceptionsAsString(getFatalSqlExceptionsAsString());
// cpd.setFatalSqlExceptionWrapper(getFatalSqlExceptionWrapperClass());
// cpd.setHouseKeepingSleepTime(getHouseKeepingSleepTime());
// cpd.setHouseKeepingTestSql(getHouseKeepingTestSql());
// cpd.setMaximumActiveTime(getMaximumActiveTime());
// cpd.setMaximumConnectionCount(getMaximumConnectionCount());
// cpd.setMaximumConnectionLifetime(getMaximumConnectionLifetime());
// cpd.setMinimumConnectionCount(getMinimumConnectionCount());
// cpd.setOverloadWithoutRefusalLifetime(getOverloadWithoutRefusalLifetime());
// cpd.setPrototypeCount(getPrototypeCount());
// cpd.setRecentlyStartedThreshold(getRecentlyStartedThreshold());
// cpd.setSimultaneousBuildThrottle(getSimultaneousBuildThrottle());
// cpd.setStatistics(getStatistics());
// cpd.setStatisticsLogLevel(getStatisticsLogLevel());
// cpd.setTrace(isTrace());
// cpd.setUrl(getDriverUrl());
// cpd.setVerbose(isVerbose());
// cpd.setJmx(isJmx());
// cpd.setJmxAgentId(getJmxAgentId());
// cpd.setTestAfterUse(isTestAfterUse());
// cpd.setTestBeforeUse(isTestBeforeUse());
// cpd.setDelegateProperties(this.delegateProperties);
// cpd.setUser(getUser());
// cpd.setPassword(getPassword());
public void setAlias(String alias) { dataSource.setAlias(alias); } public synchronized void setDriver(String driver) { try { dataSource.setDriver(driver); } catch (Exception e) { } }
public void setFatalSqlExceptionsAsString(String fatalSqlExceptionsAsString) { dataSource.setFatalSqlExceptionsAsString(fatalSqlExceptionsAsString); }
public void setHouseKeepingSleepTime(int houseKeepingSleepTime) { dataSource.setHouseKeepingSleepTime(houseKeepingSleepTime); }
public void setHouseKeepingTestSql(String houseKeepingTestSql) { dataSource.setHouseKeepingTestSql(houseKeepingTestSql); }
public void setMaximumActiveTime(int maximumActiveTime) { dataSource.setMaximumActiveTime(maximumActiveTime); }
public void setMaximumConnectionCount(int maximumConnectionCount) { dataSource.setMaximumConnectionCount(maximumConnectionCount); }
public void setMaximumConnectionLifetime(int maximumConnectionLifetime) { dataSource.setMaximumConnectionLifetime(maximumConnectionLifetime); }
public void setMinimumConnectionCount(int minimumConnectionCount) { dataSource.setMinimumConnectionCount(minimumConnectionCount); }
public void setOverloadWithoutRefusalLifetime(int overloadWithoutRefusalLifetime) { dataSource.setOverloadWithoutRefusalLifetime(overloadWithoutRefusalLifetime); }
public void setPrototypeCount(int prototypeCount) { dataSource.setPrototypeCount(prototypeCount); }
public void setRecentlyStartedThreshold(int recentlyStartedThreshold) { dataSource.setRecentlyStartedThreshold(recentlyStartedThreshold); }
public void setSimultaneousBuildThrottle(int simultaneousBuildThrottle) { dataSource.setSimultaneousBuildThrottle(simultaneousBuildThrottle); }
public void setStatistics(String statistics) { dataSource.setStatistics(statistics); }
public void setStatisticsLogLevel(String statisticsLogLevel) { dataSource.setStatisticsLogLevel(statisticsLogLevel); }
public void setTrace(boolean trace) { dataSource.setTrace(trace); }
public void setUrl(String url) { dataSource.setDriverUrl(url); }
public void setVerbose(boolean verbose) { dataSource.setVerbose(verbose); }
public void setJmx(boolean jmx) { dataSource.setJmx(jmx); }
public void setJmxAgentId(String jmxAgentId) { dataSource.setJmxAgentId(jmxAgentId); }
public void setTestAfterUse(boolean testAfterUse) { dataSource.setTestAfterUse(testAfterUse); }
public void setTestBeforeUse(boolean testBeforeUse) { dataSource.setTestBeforeUse(testBeforeUse); }
public void setDelegateProperties(String delegateProperties) { dataSource.setDelegateProperties(delegateProperties); }
public void setUser(String user) { dataSource.setUser(user); }
public void setPassword(String password) { dataSource.setPassword(password); }
public void setUsername(String username) { dataSource.setUser(username); } }
|
3. 在配置文件Configuration.xml中,可以先定义数据源的别称,然后就象POOLED和UNPOOLED一样使用别称来引用数据源。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN" ""> <configuration> <properties resource="conf/jdbc-development.properties" /> <settings> <setting name="cacheEnabled" value="false"/> </settings> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="conf/ibatis/ibatis-base-mapper.xml"/> <mapper resource="conf/ibatis/ibatis-difmnetmt-mapper.xml"/> <mapper resource="conf/ibatis/ibatis-test-mapper.xml"/> </mappers> </configuration>
|
相关资料:
1. iBatis官网用户手册:
2. IBatis3中使用自定义数据源C3P0:http://www.blogjava.net/usherlight/archive/2010/02/01/311493.html
3. 在ibatis2中使用proxool数据源:http://wt8414.javaeye.com/blog/514824
4. spring配置ibatis的jdbc方式和proxool、c3p0连接池方式:http://www.blogjava.net/landor2004/archive/2009/07/01/284978.html
阅读(1942) | 评论(0) | 转发(0) |