<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Dict.CN 在線詞典, 英語學習, 在線翻譯

    都市淘沙者

    荔枝FM Everyone can be host

    統計

    留言簿(23)

    積分與排名

    優秀學習網站

    友情連接

    閱讀排行榜

    評論排行榜

    Unit tests with H2 and iBATIS

    source : http://tech.shopzilla.com/2010/05/unit-tests-with-h2-and-ibatis/

    Unit tests with H2 and iBATIS
    Posted by Steve Corwin Friday, May 7th 
    2010 

    Since my previous post on Using HSQLDB 
    for unit testing database access code I began work on a project that needed to use iBATIS instead of JPA or Hibernate for database access. Based on a recommendation from my previous post, I decided to try H2 instead of HSQLDB as the in-memory database. This project still uses Oracle and Spring.

    H2 proved much easier when the production database is Oracle. I was able to copy DDL extracted from the Oracle database and use it (almost) unmodified in H2. The DDL ran without error in all cases I’ve tried, including “created_date date 
    default sysdate not null”. There were a couple of issues:
    1. there was a Java Boolean being stored in a 1-character varchar column. The Oracle JDBC driver translates to “0″ or “1″, which fits. The H2 JDBC driver translates to “true” or “false”. I just changed the column to “varchar2(5 char)” in the test code.
    2. date columns in H2 don’t store the time, only the date (no hours, minutes, seconds). I just changed the column to a timestamp in the test code.
    (I did 
    try H2’s Oracle compatibility mode, but it didn’t make a difference.)

    iBATIS was not so pleasant 
    for me. Because of some complexities in this service, which needs to effectively combine operations on two different database connections into one transaction, I decided to use iBATIS manual transaction demarcation. This looks simple, but wasn’t so easy to get working. The iBATIS javadocs show manual transactions as a straightforward pattern:

    view sourceprint
    ?1 try {  

    2   sqlMap.startTransaction();  

    3   // do work  

    4   sqlMap.commitTransaction();  

    5 } finally {  

    6   sqlMap.endTransaction();  

    7 } 

    However there is a subtlety: depending on the SqlMapClient configuration, the commitTransaction() and endTransaction() methods may not 
    do anything at all. This was the configuration we were getting from our existing Spring config files, and the result was that none of my changes were committed to the database. Apparently something was defaulting to having the transactions handled by com.ibatis.sqlmap.engine.transaction.external.ExternalTransaction. Looking at that source you can see that the commit() method has an empty body.

    In order to have my transactions commit, I needed to use the 
    class com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig instead. In this code the commit() method calls commit() on the underlying JDBC connection.

    Using the correct 
    class is just a matter of setting the fully-qualified class name as the value of the “transactionConfigClass” property for the SqlMapClient instance. Here is an example from applicationContext.xml:

    view sourceprint
    ?01 <bean id="sqlMapClient" 

    02 class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  

    03    <qualifier value="account"/>  

    04    <property name="configLocation">  

    05      <value>classpath:P13NSqlMapConfig.xml</value>  

    06    </property>  

    07    <property name="dataSource" ref="masterDataSource" />  

    08    <!-- without this setting the commitTransaction() method does not  

    09 commit --> 

    10    <property name="transactionConfigClass" value=  

    11 "com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig" />  

    12    

    13 </bean> 

    Note that you also need to have the connections set to not autocommit. For Oracle 
    this seems to be the default.

    Using 
    this unit-testing technique requires completing three steps:
    1. Create a class that will create the tables and (optionally) populate with test data.
    2. Create a unit test that will use DbTestUtils to test a DAO implementation.
    3. Supply a DataSource to the DAO/class under test.

    Most of what follows is the same as it was 
    for HSQLDB & Hibernate; the only real difference is the config file, which now supplies iBATIS objects instead of Hibernate/JPA. After some thought I decided to include the sections that haven’t changed so that this post could (hopefully) stand on its own.

    1. Create a class that will create the tables and (optionally) populate with test data.

    view sourceprint
    ?01 public class DbTestUtils {  

    02     public static void setupTables(Connection connection) throws SQLException {  

    03    

    04         dropTable(connection, "activation_code_mapping");  

    05    

    06         executeSql(connection, "create table activation_code_mapping (" 

    07                 + "activation_code varchar2(80 char) not null, " 

    08                 + "email_address varchar2(500 char) not null, " 

    09                 + "source varchar2(25 char) not null, " + "merchant_id number(38), " 

    10                 + "historical_merchant_name varchar2(1020 char), " 

    11                 // date columns in H2 don't store the time, only the date, so I changed it to  

    12                 // timestamp  

    13                 + "created_date timestamp default sysdate not null," 

    14                 + "constraint pk_activation_code_mapping primary key (activation_code)" + ")");  

    15     }  

    16    

    17     public static void dropSequence(Connection connection, String sequence) {  

    18         try {  

    19    

    20             executeSql(connection, "drop sequence " + sequence);  

    21             connection.commit();  

    22         } catch (SQLException se) {  

    23             // ignore exception  

    24             // System.out.println(se);  

    25         }  

    26     }  

    27    

    28     public static void dropTable(Connection connection, String table) {  

    29         try {  

    30    

    31             executeSql(connection, "drop table " + table);  

    32             connection.commit();  

    33         } catch (SQLException se) {  

    34             // ignore exception  

    35             // System.out.println(se);  

    36         }  

    37    

    38     }  

    39    

    40     public static void executeSql(Connection connection, String sql) throws SQLException {  

    41    

    42         Statement statement = connection.createStatement();  

    43         statement.execute(sql);  

    44     }  

    45 } 

    2. Create a unit test that will use DbTestUtils to test a DAO implementation.

    view sourceprint
    ?001 public class ActivationCodeMappingCacheStoreTest extends AbstractDependencyInjectionSpringContextTests {  

    002    

    003     private DataSource dataSource;  

    004     private ActivationCodeMappingCacheStore activationCodeMappingCacheStore;  

    005    

    006     @Override 

    007     protected String getConfigPath() {  

    008         return "unit-test-config.xml";  

    009     }  

    010    

    011     @Required 

    012     public void setDataSource(DataSource dataSource) {  

    013         this.dataSource = dataSource;  

    014     }  

    015    

    016     @Required 

    017     public void setActivationCodeMappingCacheStore(  

    018             ActivationCodeMappingCacheStore activationCodeMappingCacheStore) {  

    019         this.activationCodeMappingCacheStore = activationCodeMappingCacheStore;  

    020     }  

    021    

    022     @Override 

    023     protected void onSetUp() {  

    024    

    025         try {  

    026             Connection connection = dataSource.getConnection();  

    027             connection.setAutoCommit(false);  

    028    

    029             DbTestUtils.setupTables(connection);  

    030    

    031             insertTestData(connection);  

    032    

    033             // simple test to verify that the correct data was inserted into the database  

    034             Statement statement = connection.createStatement();  

    035             ResultSet resultSet = statement.executeQuery("select * from activation_code_mapping");  

    036    

    037             assertTrue(resultSet.next());  

    038             assertEquals("4fe801", resultSet.getString("activation_code"));  

    039    

    040             connection.commit();  

    041    

    042             connection.close();  

    043    

    044         } catch (SQLException se) {  

    045             throw new RuntimeException(se);  

    046         }  

    047     }  

    048    

    049     private void insertTestData(Connection connection) throws SQLException {  

    050    

    051         String sql = "insert into activation_code_mapping(activation_code, email_address, source, merchant_id, historical_merchant_name)" 

    052                 + "values ('4fe801', 'arthur@hgttg.com', '0001', 1234567, 'Slartibartfast')";  

    053         DbTestUtils.executeSql(connection, sql);  

    054     }  

    055    

    056     public void testLoad() {  

    057    

    058         // test load  

    059         String key = "4fe801";  

    060         Object foundObject = activationCodeMappingCacheStore.load(key);  

    061         assertNotNull(foundObject);  

    062    

    063         ActivationCodeMapping activationCodeMapping = (ActivationCodeMapping) foundObject;  

    064    

    065         // verify columns including date  

    066         assertEquals("4fe801", activationCodeMapping.getActivationCode());  

    067         assertEquals("arthur@hgttg.com", activationCodeMapping.getEmailAddress());  

    068         assertEquals("0001", activationCodeMapping.getSource());  

    069         assertEquals(1234567L, activationCodeMapping.getMerchantId().longValue());  

    070         assertEquals("Slartibartfast", activationCodeMapping.getHistoricalMerchantName());  

    071    

    072         assertNotNull(activationCodeMapping.getCreatedDate());  

    073         assertEquals(1, activationCodeMapping.getImplVersion());  

    074     }  

    075    

    076     public void testStore() {  

    077    

    078         final String activationCode = "1234";  

    079    

    080         // test insert  

    081         ActivationCodeMapping activationCodeMappingForInsert = new ActivationCodeMapping();  

    082         activationCodeMappingForInsert.setActivationCode(activationCode);  

    083         activationCodeMappingForInsert.setEmailAddress("ford@hgttg.com");  

    084         activationCodeMappingForInsert.setSource("000A");  

    085         activationCodeMappingForInsert.setMerchantId(7890L);  

    086         activationCodeMappingForInsert.setHistoricalMerchantName("Milliways");  

    087    

    088         activationCodeMappingCacheStore.store(activationCode, activationCodeMappingForInsert);  

    089    

    090         // verify insert  

    091         Object foundObject = activationCodeMappingCacheStore.load(activationCode);  

    092         assertNotNull(foundObject);  

    093    

    094         ActivationCodeMapping foundActivationCodeMapping = (ActivationCodeMapping) foundObject;  

    095         assertEquals(activationCode, foundActivationCodeMapping.getActivationCode());  

    096         assertEquals("ford@hgttg.com", foundActivationCodeMapping.getEmailAddress());  

    097         assertEquals("000A", foundActivationCodeMapping.getSource());  

    098         assertEquals(7890L, foundActivationCodeMapping.getMerchantId().longValue());  

    099         assertEquals("Milliways", foundActivationCodeMapping.getHistoricalMerchantName());  

    100         assertNotNull(foundActivationCodeMapping.getCreatedDate());  

    101    

    102         //   

    103     } 

    3. Supply a DataSource to the DAO/class under test.

    Once again we’re using Spring to inject the needed instances. However the config file is now specifying an instance of an iBATIS SqlMapClient.

    view sourceprint
    ?01 <?xml version="1.0" encoding="UTF-8"?>  

    02 <beans xmlns="http://www.springframework.org/schema/beans" 

    03                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

    04                 xmlns:tx="http://www.springframework.org/schema/tx" 

    05                 xsi:schemaLocation="http://www.springframework.org/schema/beans  

    06    

    07 http://www.springframework.org/schema/beans/spring-beans-2.0.xsd  

    08    

    09 http://www.springframework.org/schema/tx  

    10    

    11 http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">  

    12    

    13   <!-- create data sources connected to an in-memory H2 (not HSQLDB) database. --> 

    14   <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">  

    15     <property name="driverClass" value="org.h2.Driver"/>  

    16     <property name="jdbcUrl" value="jdbc:h2:mem:test;AUTOCOMMIT=OFF"/>  

    17     <property name="user" value="sa" />  

    18     <property name="password" value="" />  

    19   </bean>  

    20    

    21   <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  

    22     <property name="configLocation">  

    23       <value>classpath:ActivationCodeMappingSqlMapConfig.xml</value>  

    24     </property>  

    25     <property name="dataSource" ref="dataSource" />  

    26     <!-- without this setting the commitTransaction() method does not commit --> 

    27     <property name="transactionConfigClass" value="com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig" />  

    28   </bean>  

    29    

    30   <bean id="activationCodeMappingCacheStore" class="com.shopzilla.site.service.activationcode.cachestore.ActivationCodeMappingCacheStore" >  

    31     <property name="sqlMapClient" ref="sqlMapClient" />  

    32   </bean>  

    33 </beans> 

    After using both H2 
    & HSQLDB, I definitely prefer H2 and expect to use it going forward.


    posted on 2010-10-09 15:10 都市淘沙者 閱讀(735) 評論(0)  編輯  收藏 所屬分類: Hibernate/ORM

    主站蜘蛛池模板: 亚洲AV日韩精品久久久久久久| 亚洲人成色77777| 亚洲精品无码专区久久| 免费看国产成年无码AV片| 亚洲人成小说网站色| 日韩在线a视频免费播放| 美国免费高清一级毛片| 亚洲欧洲自拍拍偷精品 美利坚| 9久热这里只有精品免费| 亚洲成a人片77777kkkk| 亚洲美女视频免费| 亚洲色成人网站WWW永久四虎| 四虎成人免费网址在线| 免费看美女午夜大片| 国产AV无码专区亚洲AWWW| 久久青草免费91观看| 亚洲综合中文字幕无线码| 国产99视频免费精品是看6 | 中国一级特黄的片子免费 | 四虎永久在线观看免费网站网址 | 精品国产亚洲第一区二区三区| 免费国产a国产片高清| 一级看片免费视频囗交| 久久国产精品亚洲综合| 成人免费午夜无码视频| 国产亚洲精品美女久久久久| 亚洲色精品88色婷婷七月丁香| 久久99国产综合精品免费| 亚洲精品无AMM毛片| 国产亚洲精品久久久久秋霞| 97av免费视频| 爱情岛论坛免费视频| 久久亚洲精品无码VA大香大香| 永久免费观看的毛片的网站| 韩国免费A级毛片久久| 亚洲一区二区三区免费观看| 亚洲国产高清精品线久久| 88xx成人永久免费观看| MM1313亚洲精品无码久久| 久久夜色精品国产亚洲| 日本牲交大片免费观看|