IBatis3中使用自定义数据源C3P0

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类来进行数据源属性的设置,而是使用反射机制直接调用数据源的方法来设置参数。
这就要求配置文件中的参数名称必须与数据源类中的方法名匹配.
 1  public   class  C3p0DataSourceFactory  implements  DataSourceFactory {
 2 
 3       private  DataSource dataSource;
 4 
 5       public  C3p0DataSourceFactory() {
 6          dataSource  =   new  C3p0DataSource();
 7      }
 8 
 9       public  DataSource getDataSource() {
10           return  dataSource;
11      }
12 
13       public   void  setProperties(Properties properties) {
14          Properties driverProperties  =   new  Properties();
15          MetaObject metaDataSource  =  MetaObject.forObject(dataSource);
16           for  (Object key : properties.keySet()) {
17              String propertyName  =  (String) key;
18               if  (propertyName.startsWith(DRIVER_PROPERTY_PREFIX)) {
19                  String value  =  properties.getProperty(propertyName);
20                  driverProperties.setProperty(propertyName
21                          .substring(DRIVER_PROPERTY_PREFIX_LENGTH), value);
22              }  else   if  (metaDataSource.hasSetter(propertyName)) {
23                  String value  =  (String) properties.get(propertyName);
24                  Object convertedValue  =  convertValue(metaDataSource,
25                          propertyName, value);
26                  metaDataSource.setValue(propertyName, convertedValue);
27              }  else  {
28                   throw   new  DataSourceException( " Unkown DataSource property:  "
29                           +  propertyName);
30              }
31          }
32           if  (driverProperties.size()  >   0 ) {
33              metaDataSource.setValue( " driverProperties " , driverProperties);
34          }
35      }
36 
37      @SuppressWarnings( " unchecked " )
38       private  Object convertValue(MetaObject metaDataSource, String propertyName,
39              String value) {
40          Object convertedValue  =  value;
41          Class targetType  =  metaDataSource.getSetterType(propertyName);
42           if  (targetType  ==  Integer. class   ||  targetType  ==   int . class ) {
43              convertedValue  =  Integer.valueOf(value);
44          }  else   if  (targetType  ==  Long. class   ||  targetType  ==   long . class ) {
45              convertedValue  =  Long.valueOf(value);
46          }  else   if  (targetType  ==  Boolean. class   ||  targetType  ==   boolean . class ) {
47              convertedValue  =  Boolean.valueOf(value);
48          }
49           return  convertedValue;
50      }
51 
52       private   static   final  String DRIVER_PROPERTY_PREFIX  =   " driver. " ;
53       private   static   final   int  DRIVER_PROPERTY_PREFIX_LENGTH  =  DRIVER_PROPERTY_PREFIX
54              .length();
55 
56  }
57 

2. 数据源类,其中的一堆setter就是用于设置属性的。
 1  public   class  C3p0DataSource  implements  DataSource {
 2 
 3       private  ComboPooledDataSource dataSource;
 4       public  C3p0DataSource() {
 5           this .dataSource  =   new  ComboPooledDataSource();
 6      }
 7      
 8       public  Connection getConnection()  throws  SQLException {
 9           return  dataSource.getConnection();
10      }
11 
12       public  Connection getConnection(String username, String password)
13               throws  SQLException {
14           return  dataSource.getConnection(username, password);
15      }
16 
17       public  PrintWriter getLogWriter()  throws  SQLException {
18           return  dataSource.getLogWriter();
19      }
20 
21       public   int  getLoginTimeout()  throws  SQLException {
22           return  dataSource.getLoginTimeout();
23      }
24 
25       public   void  setLogWriter(PrintWriter out)  throws  SQLException {
26          dataSource.setLogWriter(out);
27      }
28 
29       public   void  setLoginTimeout( int  seconds)  throws  SQLException {
30          dataSource.setLoginTimeout(seconds);
31      }
32      
33      
34       public   synchronized   void  setDriver(String driver) {
35           try  {
36              dataSource.setDriverClass(driver);
37          }  catch  (Exception e) {
38          }
39      }
40      
41       public   void  setUrl(String url) {
42          dataSource.setJdbcUrl(url);
43      }
44      
45       public   void  setUsername(String username) {
46            dataSource.setUser(username);
47      }
48 
49       public   void  setPassword(String password) {
50          dataSource.setPassword(password);
51      }
52      
53       public   void  setInitialPoolSize( int  initialPoolSize) {
54          dataSource.setInitialPoolSize(initialPoolSize);
55      }
56      
57       public   void  setMaxPoolSize( int  maxPoolSize) {
58          dataSource.setMaxPoolSize(maxPoolSize);
59      }
60        
61       public   void  setMinPoolSize( int  minPoolSize) {
62          dataSource.setMinPoolSize(minPoolSize);
63      }
64      
65       public   void  setPreferredTestQuery(String preferredTestQuery) {
66          dataSource.setPreferredTestQuery(preferredTestQuery);
67      }
68      
69       public   void  setPoolPingQuery(String poolPingQuery) {
70          dataSource.setPreferredTestQuery(poolPingQuery);
71      }
72  }

3. 在配置文件Configuration.xml中,可以先定义数据源的别称,然后就象POOLED和UNPOOLED一样使用别称来引用数据源。
<Configuration>
    ...
    <typeAlias>
        <typeAlias type="com.test.datasource.C3p0DataSourceFactory" alias="C3P0"/>
    </typeAlias>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="C3P0">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
                <property name="poolPingQuery" value="${pingquery}"/>           
            </dataSource>
        </environment>
    </environments>
    ...
<Configuration>





你可能感兴趣的:(IBatis3中使用自定义数据源C3P0)