<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 都市淘沙者 閱讀(734) 評論(0)  編輯  收藏 所屬分類: Hibernate/ORM

    主站蜘蛛池模板: 亚洲中文字幕久久精品无码APP| 国产在线观看免费不卡| 国拍在线精品视频免费观看| 成人AV免费网址在线观看| 免费无码又爽又高潮视频| 国产大片91精品免费观看男同| 亚洲欧洲久久久精品| 亚洲αv在线精品糸列| 亚洲电影在线免费观看| 亚洲AV永久无码精品放毛片 | 亚洲熟妇av一区二区三区| 亚洲AV无码成人精品区在线观看| 亚洲国产成人精品青青草原| 欧洲亚洲国产精华液| 中文字幕在线免费看线人| 一级女人18毛片免费| 一级毛片直播亚洲| 亚洲人成影院在线| 亚洲高清毛片一区二区| 免费一区二区无码东京热| 在线观看av永久免费| 久久久久一级精品亚洲国产成人综合AV区| 亚洲电影中文字幕| 亚洲av成人一区二区三区观看在线 | 亚洲 暴爽 AV人人爽日日碰| 春意影院午夜爽爽爽免费| 未满十八18禁止免费无码网站 | 亚洲国产一区国产亚洲| 亚洲av无码无线在线观看| 日本免费中文视频| 日韩高清在线免费观看| 亚洲大尺度无码专区尤物| 亚洲GV天堂无码男同在线观看| 男人进去女人爽免费视频国产| 午夜两性色视频免费网站| 亚洲另类激情综合偷自拍| 黄色一级毛片免费| 永久免费毛片在线播放| 亚洲韩国精品无码一区二区三区| 亚洲日韩中文字幕无码一区| APP在线免费观看视频|