云自无心水自闲

天平山上白云泉,云自无心水自闲。何必奔冲山下去,更添波浪向人间!
posts - 288, comments - 524, trackbacks - 0, articles - 6
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

IBatis3中使用自定义数据源C3P0

Posted on 2010-02-01 12:57 云自无心水自闲 阅读(3897) 评论(2)  编辑  收藏 所属分类: Java心得体会iBatis
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>






评论

# re: IBatis3中使用自定义数据源C3P0  回复  更多评论   

2010-11-07 01:39 by wppurking
1. public class C3p0 extends UnpooledDataSourceFactory;
(com.package.c3p0_ibatis)

2. 配置文件中设置
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="com.package..C3p0"> <!-- 配置全名 -->
<!-- 连接池设置由C3p0.properties自己决定 -->
</dataSource>
</environment>
</environments>

3. 将 c3p0.properties 文件放入 classpath 中

这样省去很多代码,还可以完全设置 c3p0 的各个配置属性,简单很多,试一下?

# re: IBatis3中使用自定义数据源C3P0  回复  更多评论   

2010-11-07 01:41 by wppurking
补充一下:继承后需要与 PooledDataSourceFactory 做同样的操作,编写自己的无参构造方法: this.dataSource = new ComboPooledDataSource();

只有注册用户登录后才能发表评论。


网站导航: