IBatis3中使用自定義數據源C3P0
Posted on 2010-02-01 12:57 云自無心水自閑 閱讀(3916) 評論(2) 編輯 收藏 所屬分類: Java 、心得體會 、iBatisIBatis2中提供了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類來進行數據源屬性的設置,而是使用反射機制直接調用數據源的方法來設置參數。
這就要求配置文件中的參數名稱必須與數據源類中的方法名匹配.
2. 數據源類,其中的一堆setter就是用于設置屬性的。
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>
如果要實現自定義的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
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 }
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>