知识点

相关文章

更多

最近更新

更多

【第八章】 对ORM的支持 之 8.3 集成iBATIS ——跟我学spring3

2019-03-01 14:32|来源: 开涛

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):

  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)定义:

  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)定义:

  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

  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创建和删除表:

  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进行对象持久化:

  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的使用:

  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实现:

  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查询:

  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中添加如下配置:

  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):

  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):

  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)定义:

  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有如下不同:

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

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

  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中添加如下配置:

  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):

  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

相关问答

更多
  • 请问你是想把你输入的数字保存到文本区的,,, 而大于1000个字符后,,,你无法确定是否需要保存到文本区吗? 对于以上, 我的理解是,你完全可以设定文本框最大字符长度。。
  • IbatisAdmPacVoucherDAO继承了BaseDAO类,对于继承来的属性,这里用parent="sqlMapClientDAO" 来获得。 我们找到sqlMapClientDAO的声明如下:
  • 我想你看的参考手册说的那种配置绝对不是Spring的获取方式,Spring自身有一个ibatis模板类SqlMapClientTemplate,你继承这个类就可以获取你想要的东西,这是一种叫做模板方法的设计模式,Spring使用这种设计模式来管理Dao的通用增删改查方法,很方便。 还有,最好把你的出错信息,以及配置发上来,这样才能更准确的对问题进行定位。
  • 很有上进心的孩子。所以有件事情你一定要及早知道。程序员这个职位,其实含义很广。简单点去理解,3个月的时间,懂一点皮毛,就可以。但是你会的越多,就越知道自己不会的更多。所以不要求速度的门槛,要筑造好坚实的基础。你学的教材我不知道,但是几乎所有的书,只能教给你手段,不能带给你思想。而这正是程序员和IT民工的差别所在。20开始学不晚。十分不晚。所以你应该专心学习,避免急功近利。 如果你已经能够实际的工作,那么继续提高除了熟练度和开拓编程思想以外,还包括两个重要方向:一是横向学习。比如你主业是c++,在你达到一定高 ...
  • 这里有很多问题。 首先,我在你的小例子中计算了JNDI查找字符串的三个引用。 如果可能的话,DRY会告诉你写一次并提及它。 其次,我不太欣赏你的DAO。 这真的是你在写什么,或者这只是一个例子? 我不认为这是春天的成语。 没有界面。 你如何做没有一个的声明式交易? 我建议您更仔细地查看iBatis的Spring文档 。 第三,我建议使用JUnit 4.4或者更好的是TestNG成语 - 注释。 同时检查Spring @ContextConfiguration以在setUp中注入所需的bean。 第四,您的D ...
  • Apache Gora开源框架为大数据提供了内存数据模型和持久性。 Gora支持持久存储到列存储,键值存储,文档存储和RDBMS,并通过广泛的Apache Hadoop™MapReduce支持分析数据。 - 请参阅: http : //gora.apache.org/#sthash.aHUqfiFl.dpuf The Apache Gora open source framework provides an in-memory data model and persistence for big data. ...
  • 这是一个开放的JIRA问题( SPR-5991 )。 它具有标记为Spring 3.1的iBatis3支持 There's an open JIRA issue for this (SPR-5991). It has iBatis3 support tagged for Spring 3.1
  • spring没有自己的orm实现。 spring的orm是一个抽象层,它为你使用的实际orm实现添加了增强功能,如hibernate / JDO或JPA。 spring does not have its own orm implementation. spring's orm is a layer of abstraction that adds enhancements to the actual orm implementation that you use like hibernate/JDO or ...
  • //此ios8通知的条件... if ([[UIApplication sharedApplication] respondsToSelector:@selector(registerUserNotificationSettings:)]) { [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificat ...