对ORM的支持 之 8.3 集成iBATIS ——跟我学spring3

来源:互联网 发布:淘宝卖家能屏蔽震动 编辑:程序博客网 时间:2024/04/30 05:19

8.3  集成iBATIS

       iBATIS是一个半自动化的ORM框架,需要通过配置方式指定映射SQL语句,而不是由框架本身生成(如hibernate自动生成对应SQL来持久化对象),即Hibernate属于全自动ORM框架。

spring提供对iBATIS 2.X的集成,提供一致的异常体系、一致的DAO访问支持、Spring管理事务支持。

       Spring 2.5.5+版本支持iBATIS 2.3+版本,不支持低版本。

8.3.1  如何集成

       Spring通过使用如下Bean进行集成iBATIS:

  • SqlMapClientFactoryBean:用于集成iBATIS。

         configLocation和configLocations:用于指定SQL Map XML配置文件,用于指定如数据源等配置信息;

         mappingLocations:用于指定SQL Map映射文件,即半自动概念中的SQL语句定义;

         sqlMapClientProperties:定义iBATIS 配置文件配置信息;

         dataSource:定义数据源。

 

如果在Spring配置文件中指定了DataSource,就不要在iBATIS配置文件指定了,否则Spring配置文件指定的DataSource将覆盖iBATIS配置文件中定义的DataSource。

 

       接下来示例一下如何集成iBATIS:

1、准备需要的jar包,从spring-framework-3.0.5.RELEASE-dependencies.zip中拷贝如下jar包:

 

 com.springsource.com.ibatis-2.3.4.726.jar

  

2、 对象模型定义,此处使用第七章中的UserModel;

 

3、 iBATIS映射定义(chapter8/sqlmaps/UserSQL.xml):


java代码:
查看复制到剪贴板打印
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"  
  3.     "http://ibatis.apache.org/dtd/sql-map-2.dtd">  
  4. <sqlMap namespace="UserSQL">  
  5.   <statement id="createTable">  
  6.     <!--id自增主键从0开始 -->  
  7.     <![CDATA[  
  8.         create memory table test(  
  9.           id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,   
  10.           name varchar(100))  
  11.     ]]>  
  12.   </statement>  
  13.   <statement id="dropTable">  
  14.     <![CDATA[  drop table test  ]]>  
  15.   </statement>  
  16.   <insert id="insert" parameterClass="cn.javass.spring.chapter7.UserModel">  
  17.     <![CDATA[  
  18.       insert into test(name) values (#myName#)  
  19.     ]]>  
  20.     <selectKey resultClass="int" keyProperty="id" type="post">  
  21.       <!-- 获取hsqldb插入的主键 -->  
  22.       call identity();  
  23.       <!-- mysql使用select last_insert_id();获取插入的主键 -->  
  24.     </selectKey>  
  25.   </insert>  
  26. </sqlMap>  
  27.    
  28.    


4、 iBATIS配置文件(chapter8/sql-map-config.xml)定义:

 

java代码:
查看复制到剪贴板打印
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"  
  3.     "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">  
  4.    
  5. <sqlMapConfig>  
  6.     <settings enhancementEnabled="true" useStatementNamespaces="true"  
  7.         maxTransactions="20" maxRequests="32" maxSessions="10"/>  
  8.     <sqlMap resource="chapter8/sqlmaps/UserSQL.xml"/>  
  9. </sqlMapConfig>  
  10.    
  11.    

 

5、 数据源定义,此处使用第7章的配置文件,即“chapter7/ applicationContext-resources.xml”文件。

 

6、 SqlMapClient配置(chapter8/applicationContext-ibatis.xml)定义:

 

java代码:
查看复制到剪贴板打印
  1. <bean id="sqlMapClient"  
  2.     class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  
  3.     <!-- 1、指定数据源 -->  
  4.     <property name="dataSource" ref="dataSource"/>  
  5.     <!-- 2、指定配置文件 -->  
  6.     <property name="configLocation" value="chapter8/sql-map-config.xml"/>  
  7. </bean>  

 

7、 获取SqlMapClient:

 

java代码:
查看复制到剪贴板打印
  1. package cn.javass.spring.chapter8;  
  2. //省略import  
  3. public class IbatisTest {  
  4.     private static SqlMapClient sqlMapClient;  
  5.     @BeforeClass  
  6.     public static void setUpClass() {  
  7.       String[] configLocations = new String[] {  
  8.           "classpath:chapter7/applicationContext-resources.xml",  
  9.           "classpath:chapter8/applicationContext-ibatis.xml"};  
  10.       ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);  
  11.       sqlMapClient = ctx.getBean(SqlMapClient.class);  
  12.   }  
  13. }  

 

此处我们使用了chapter7/applicationContext-resources.xml定义的“dataSource”数据源,通过ctx.getBean(SqlMapClient.class)获取SqlMapClient。

 

 

8、 通过SqlMapClient创建和删除表:

 

java代码:
查看复制到剪贴板打印
  1. @Before  
  2. public void setUp() throws SQLException {  
  3.     sqlMapClient.update("UserSQL.createTable");  
  4. }  
  5. @After  
  6. public void tearDown() throws SQLException {  
  7.     sqlMapClient.update("UserSQL.dropTable");  
  8. }  

 

 

9、 使用SqlMapClient进行对象持久化:


java代码:
查看复制到剪贴板打印
  1.       
  2. @Test  
  3. public void testFirst() throws SQLException {  
  4.     UserModel model = new UserModel();  
  5.     model.setMyName("test");  
  6.     SqlMapSession session = null;  
  7.     try {  
  8.         session = sqlMapClient.openSession();  
  9.         beginTransaction(session);  
  10.         session.insert("UserSQL.insert", model);  
  11.         commitTransaction(session);  
  12.     } catch (SQLException e) {  
  13.         rollbackTransacrion(session);  
  14.         throw e;  
  15.     } finally {  
  16.         closeSession(session);  
  17.     }  
  18. }  
  19. private void closeSession(SqlMapSession session) {  
  20.    session.close();  
  21. }  
  22. private void rollbackTransacrion(SqlMapSession session) throws SQLException {  
  23.     if(session != null) {  
  24.         session.endTransaction();  
  25.     }           
  26. }  
  27. private void commitTransaction(SqlMapSession session) throws SQLException {  
  28.     session.commitTransaction();  
  29. }  
  30. private void beginTransaction(SqlMapSession session) throws SQLException {  
  31.     session.startTransaction();  
  32. }  
  33.    


同样令人心烦的事务管理和冗长代码,Spring通用提供了SqlMapClientTemplate模板类来解决这些问题。

 

8.3.2  使用 SqlMapClientTemplate

SqlMapClientTemplate模板类同样用于简化事务管理及常见操作,类似于JdbcTemplate模板类,对于复杂操作通过提供SqlMapClientCallback回调接口来允许更复杂的操作。

       接下来示例一下SqlMapClientTemplate的使用:

 

java代码:
查看复制到剪贴板打印
  1. @Test  
  2. public void testSqlMapClientTemplate() {  
  3. SqlMapClientTemplate sqlMapClientTemplate =  
  4. new SqlMapClientTemplate(sqlMapClient);  
  5.     final UserModel model = new UserModel();  
  6.     model.setMyName("myName");  
  7.     sqlMapClientTemplate.insert("UserSQL.insert", model);  
  8.     //通过回调允许更复杂操作  
  9.     sqlMapClientTemplate.execute(new SqlMapClientCallback<Void>() {  
  10.         @Override  
  11.         public Void doInSqlMapClient(SqlMapExecutor session) throws SQLException {  
  12.             session.insert("UserSQL.insert", model);  
  13.             return null;  
  14.     }});  
  15. }  
  16.    

 

通过new SqlMapClientTemplate(sqlMapClient)创建HibernateTemplate模板类对象,通过调用模板类的save方法持久化对象,并且自动享受到Spring管理事务的好处。

 

而且SqlMapClientTemplate提供使用SqlMapClientCallback回调接口的方法execute用来支持复杂操作,当然也自动享受到Spring管理事务的好处。

 

8.3.3集成iBATIS及最佳实践

       类似于JdbcDaoSupport类,Spring对iBATIS也提供了SqlMapClientDaoSupport类来支持一致的数据库访问。SqlMapClientDaoSupport也是DaoSupport实现:

       接下来示例一下Spring集成iBATIS的最佳实践:

 

1、 定义Dao接口,此处使用cn.javass.spring.chapter7.dao.IUserDao:

 

2、 定义Dao接口实现,此处是iBATIS实现:

 

java代码:
查看复制到剪贴板打印
  1. package cn.javass.spring.chapter8.dao.ibatis;  
  2. //省略import  
  3. public class UserIbatisDaoImpl extends SqlMapClientDaoSupport  
  4.     implements IUserDao {  
  5.     @Override  
  6.     public void save(UserModel model) {  
  7.         getSqlMapClientTemplate().insert("UserSQL.insert", model);  
  8.     }  
  9.     @Override  
  10.     public int countAll() {  
  11.         return (Integer) getSqlMapClientTemplate().queryForObject("UserSQL.countAll");  
  12.     }  
  13. }  

 

3、修改iBATS映射文件(chapter8/sqlmaps/UserSQL.xml),添加countAll查询:

 

java代码:
查看复制到剪贴板打印
  1. <select id="countAll" resultClass="java.lang.Integer">  
  2.     <![CDATA[ select count(*) from test ]]>     
  3. </select>  

此处注意首先iBATIS实现放在dao.ibaitis包里,其次实现类命名如UserIbatisDaoImpl,即×××IbatisDaoImpl,当然如果自己有更好的命名规范可以遵循自己的,此处只是提个建议。

 

4、进行资源配置,使用resources/chapter7/applicationContext-resources.xml:

 

5、dao定义配置,在chapter8/applicationContext-ibatis.xml中添加如下配置:

 

java代码:
查看复制到剪贴板打印
  1. <bean id="abstractDao" abstract="true">  
  2.     <property name="sqlMapClient" ref="sqlMapClient"/>  
  3. </bean>     
  4. <bean id="userDao"  
  5.       class="cn.javass.spring.chapter8.dao.ibatis.UserIbatisDaoImpl"  
  6.       parent="abstractDao"/>   

 

首先定义抽象的abstractDao,其有一个sqlMapClient属性,从而可以让继承的子类自动继承sqlMapClient属性注入;然后定义userDao,且继承abstractDao,从而继承sqlMapClient注入;我们在此给配置文件命名为applicationContext-ibatis.xml表示iBAITIS实现。

 

 

5、 最后测试一下吧(cn.javass.spring.chapter8. IbatisTest): 

 

java代码:
查看复制到剪贴板打印
  1. @Test  
  2. public void testBestPractice() {  
  3.     String[] configLocations = new String[] {  
  4.             "classpath:chapter7/applicationContext-resources.xml",  
  5.             "classpath:chapter8/applicationContext-ibatis.xml"};  
  6.     ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);  
  7.     IUserDao userDao = ctx.getBean(IUserDao.class);  
  8.     UserModel model = new UserModel();  
  9.     model.setMyName("test");  
  10.     userDao.save(model);  
  11.     Assert.assertEquals(1, userDao.countAll());  
  12. }  

 

和Spring JDBC框架的最佳实践完全一样,除了使用applicationContext-ibatis.xml代替了applicationContext-jdbc.xml,其他完全一样。也就是说,DAO层的实现替换可以透明化。

 

8.3.4Spring+iBATIS的CURD

Spring集成iBATIS进行CURD(增删改查),也非常简单,首先配置映射文件,然后调用SqlMapClientTemplate相应的函数进行操作即可,此处就不介绍了。

 

 

 

 

8.3.5集成MyBatis及最佳实践

(本笔记写于2010年底)

 

2010年4月份 iBATIS团队发布iBATIS 3.0的GA版本的候选版本,在iBATIS 3中引入了泛型、注解支持等,因此需要Java5+才能使用,但在2010年6月16日,iBATIS团队决定从apache迁出并迁移到Google Code,并更名为MyBatis。目前新网站上文档并不完善。

 

目前iBATIS 2.x和MyBatis 3不是100%兼容的,如配置文件的DTD变更,SqlMapClient直接由SqlSessionFactory代替了,包名也有com.ibatis变成org.ibatis等等。

ibatis 3.x和MyBatis是兼容的,只需要将DTD变更一下就可以了。

 

感兴趣的朋友可以到http://www.mybatis.org/官网去下载最新的文档学习,作者只使用过iBATIS2.3.4及以前版本,没在新项目使用过最新的iBATIS 3.x和Mybatis,因此如果读者需要在项目中使用最新的MyBatis,请先做好调研再使用。

 

       接下来示例一下Spring集成MyBatis的最佳实践:

 

1、准备需要的jar包,到MyBatis官网下载mybatis 3.0.4版本和mybatis-spring 1.0.0版本,并拷贝如下jar包到类路径:


mybatis-3.0.4\mybatis-3.0.4.jar              //核心MyBatis包

mybatis-spring-1.0.0\mybatis-spring-1.0.0.jar  //集成Spring包

 

2、对象模型定义,此处使用第七章中的UserModel;

 

3、MyBatis映射定义(chapter8/sqlmaps/UserSQL-mybatis.xml):


java代码:
查看复制到剪贴板打印
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
  3.      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  
  4. <mapper namespace="UserSQL">  
  5.     <sql id="createTable">  
  6.     <!--id自增主键从0开始 -->  
  7.     <![CDATA[  
  8.       create memory table test(  
  9.         id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,   
  10.         name varchar(100))  
  11.     ]]>  
  12.     </sql>  
  13.     <sql id="dropTable">  
  14.     <![CDATA[ drop table test ]]>  
  15.     </sql>  
  16.     <insert id="insert" parameterType="cn.javass.spring.chapter7.UserModel">  
  17.     <![CDATA[ insert into test(name) values (#{myName}) ]]>  
  18.         <selectKey resultType="int" keyProperty="id" order="AFTER">  
  19.             <!-- 获取hsqldb插入的主键 -->  
  20.             call identity();  
  21.             <!-- mysql使用select last_insert_id();获取插入的主键 -->  
  22.         </selectKey>  
  23.     </insert>  
  24.     <select id="countAll" resultType="java.lang.Integer">  
  25.     <![CDATA[ select count(*) from test ]]>     
  26.     </select>  
  27. </mapper>  
  28.    
  29.    

     从映射定义中可以看出MyBatis与iBATIS2.3.4有如下不同:

  • http://ibatis.apache.org/dtd/sql-map-2.dtd 废弃,而使用http://mybatis.org/dtd/mybatis-3-mapper.dtd。
  • <sqlMap>废弃,而使用<mapper>标签;
  • <statement>废弃了,而使用<sql>标签;
  • parameterClass属性废弃,而使用parameterType属性;
  • resultClass属性废弃,而使用resultType属性;
  • #myName#方式指定命名参数废弃,而使用#{myName}方式。

 

3、 MyBatis配置文件(chapter8/sql-map-config-mybatis.xml)定义:

 

java代码:
查看复制到剪贴板打印
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
  3.     "http://mybatis.org/dtd/mybatis-3-config.dtd">  
  4. <configuration>  
  5.     <settings>  
  6.         <setting name="cacheEnabled" value="false"/>  
  7.     </settings>  
  8.     <mappers>  
  9.         <mapper resource="chapter8/sqlmaps/UserSQL-mybatis.xml"/>  
  10.     </mappers>  
  11. </configuration>  

     从配置定义中可以看出MyBatis与iBATIS2.3.4有如下不同:

  • http://ibatis.apache.org/dtd/sql-map-config-2.dtd废弃,而使用http://mybatis.org/dtd/mybatis-3-config.dtd;
  • < sqlMapConfig >废弃,而使用<configuration>;
  • settings属性配置方式废弃,而改用子标签< setting name=".." value=".."/>方式指定属性,且一些属性被废弃,如maxTransactions;
  • < sqlMap>废弃,而采用<mappers>标签及其子标签<mapper>定义。

 

4、 定义Dao接口,此处使用cn.javass.spring.chapter7.dao. IUserDao:

 

5、 定义Dao接口实现,此处是MyBatis实现:

 

java代码:
查看复制到剪贴板打印
  1. package cn.javass.spring.chapter8.dao.mybatis;  
  2. //省略import  
  3. public class UserMybatisDaoImpl extends SqlSessionDaoSupport  
  4. implements IUserDao {  
  5.     @Override  
  6.     public void save(UserModel model) {  
  7.         getSqlSession().insert("UserSQL.insert", model);  
  8.     }  
  9.     @Override  
  10.     public int countAll() {  
  11.         return (Integer) getSqlSession().selectOne("UserSQL.countAll");  
  12.     }  
  13. }  
  14.    

 

     和Ibatis集成方式不同的有如下地方:

  • 使用SqlSessionDaoSupport来支持一致性的DAO访问,该类位于org.mybatis.spring.support包中,非Spring提供;
  • 使用getSqlSession方法获取SqlSessionTemplate,在较早版本中是getSqlSessionTemplate方法名,不知为什么改成getSqlSession方法名,因此这个地方在使用时需要注意。
  •  SqlSessionTemplate是SqlSession接口的实现,并且自动享受Spring管理事务好处,因此从此处可以推断出为什么把获取模板类的方法名改为getSqlSession而不是getSqlSessionTemplate。

6、进行资源配置,使用resources/chapter7/applicationContext-resources.xml:

 

7、dao定义配置,在chapter8/applicationContext-mybatis.xml中添加如下配置:

 

java代码:
查看复制到剪贴板打印
  1. <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  
  2.   <property name="dataSource" ref="dataSource"/><!-- 1、指定数据源 -->  
  3.   <property name="configLocation" value="chapter8/sql-map-config-mybatis.xml"/>  
  4. </bean>  
  5. <bean id="abstractDao" abstract="true">  
  6.    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>  
  7. </bean>     
  8. <bean id="userDao"  
  9.            class="cn.javass.spring.chapter8.dao.mybatis.UserMybatisDaoImpl"  
  10.            parent="abstractDao"/>   

 

   和Ibatis集成方式不同的有如下地方:

  • SqlMapClient类废弃,而使用SqlSessionFactory代替;
  • 使用SqlSessionFactoryBean进行集成MyBatis。

首先定义抽象的abstractDao,其有一个sqlSessionFactory属性,从而可以让继承的子类自动继承sqlSessionFactory属性注入;然后定义userDao,且继承abstractDao,从而继承sqlSessionFactory注入;我们在此给配置文件命名为applicationContext-mybatis.xml表示MyBatis实现。

 

 

8、最后测试一下吧(cn.javass.spring.chapter8. IbatisTest):


java代码:
查看复制到剪贴板打印
  1. @Test  
  2. public void testMybatisBestPractice() {  
  3.     String[] configLocations = new String[] {  
  4.         "classpath:chapter7/applicationContext-resources.xml",  
  5.         "classpath:chapter8/applicationContext-mybatis.xml"};  
  6.      ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);  
  7.     IUserDao userDao = ctx.getBean(IUserDao.class);  
  8.     UserModel model = new UserModel();  
  9.     model.setMyName("test");  
  10.     userDao.save(model);  
  11.     Assert.assertEquals(1, userDao.countAll());  
  12. }  
  13.    
  14.    


和Spring 集成Ibatis的最佳实践完全一样,除了使用applicationContext-mybatis.xml代替了applicationContext-ibatis.xml,其他完全一样,且MyBatis 3.x与Spring整合只能运行在Spring3.x。

             

在写本书时,MyBatis与Spring集成所定义的API不稳定,且期待Spring能在发布新版本时将加入对MyBatis的支持。

 

 

原创内容,转载请注明出处【http://sishuok.com/forum/blogPost/list/0/2498.html】

0 0
原创粉丝点击