Spring数据库访问之iBatis(一)

来源:互联网 发布:思源物业收费软件 编辑:程序博客网 时间:2024/05/03 17:44

Spring数据库访问之iBatis(一)

    博客分类: 
  • 框架技术
ibatisspringsqljdbcjava 
    为了丰富博客专栏【Spring数据库访问系列】的内容,完善Spring数据库访问的体系,现在我们介绍Spring对iBatis的支持。 
    相对于Hibernate等ORM框架的全自动SQL,那么iBatis则属于半自动化的ORM框架,我们需要编写SQL语句,由iBatis进行数据库访问,返回结果。而iBatis可以为我们做的更多,比如对查询结果的封装等等。虽然不如全自动SQL方便,但是SQL的主动权却在我们开发人员的手中,对SQL优化的掌控则是很直接的。对于Hibernate和iBatis的其它讨论,不是我们探究的范围。 
当前iBatis的版本为3,其名称也已经更改为MyBatis。而Spring更新到3.1都没有对MyBatis进行支持,但是MyBatis团队已经自行开发了Spring的支持。我们以Spring为主,仍然使用对iBatis2的支持来进行说明。 
首先是构建开发环境,我们仍然使用Maven作为构建环境,创建项目,本文的示例基于“联系人管理”功能来展示:
Java代码  收藏代码
  1. package org.ourpioneer.contact.bean;  
  2. public class Contact {  
  3.     private Long id;  
  4.     private String name;  
  5.     private String gender;  
  6.     private String mobile;  
  7.     private String address;  
  8.     //省略getter和setter方法  
  9.     @Override  
  10.     public String toString() {  
  11.         return "Contact [id=" + id + ", name=" + name + ", gender=" + gender  
  12.                 + ", mobile=" + mobile + ", address=" + address + "]";  
  13.     }  
  14. }  

    编写一个Contact类来描述联系人的一些特征,为了简便,我们使用5个字段就够了,实体类是很简单的。下面是添加类库了,要访问数据库,不能少了数据库驱动,我们使用MySQL数据库,在pom.xml中添加依赖: 
Xml代码  收藏代码
  1. <dependency>  
  2.     <groupId>mysql</groupId>  
  3.     <artifactId>mysql-connector-java</artifactId>  
  4.     <version>5.1.14</version>  
  5.     <type>jar</type>  
  6.     <scope>compile</scope>  
  7. </dependency>  

    同时在数据库中建表,因为iBatis还没有自动建表的功能: 
Sql代码  收藏代码
  1. CREATE TABLE `contact` (  
  2. `ID`  int(11) NOT NULL AUTO_INCREMENT ,  
  3. `NAME`  varchar(20) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL ,  
  4. `GENDER`  varchar(10) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL ,  
  5. `MOBILE`  varchar(11) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL ,  
  6. `ADDRESS`  varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL ,  
  7. PRIMARY KEY (`ID`)  
  8. )  
  9. ENGINE=InnoDB  
  10. DEFAULT CHARACTER SET=latin1 COLLATE=latin1_swedish_ci  
  11. AUTO_INCREMENT=1  
  12. ROW_FORMAT=COMPACT  
  13. ;  

    加好驱动,创建好数据库表,那么程序访问需要配置连接池,这里我们使用BoneCP连接池,在pom.xml中加入相关依赖: 
Xml代码  收藏代码
  1. <repositories>  
  2.     <repository>  
  3.         <releases>  
  4.             <updatePolicy>always</updatePolicy>  
  5.         </releases>  
  6.         <snapshots>  
  7.             <updatePolicy>always</updatePolicy>  
  8.         </snapshots>  
  9.         <id>Jolbox</id>  
  10.         <name>Jolbox Repositories</name>  
  11.         <url>http://jolbox.com/bonecp/downloads/maven</url>  
  12.     </repository>  
  13. </repositories>  

    因为BoneCP的Maven仓库不在Maven的中央仓库中,所以必须加入以上代码到pom.xml中,这点可以在BoneCP的官方网站(http://jolbox.com/)中获得,下面就是加入依赖了,就没有什么多说的了: 
Xml代码  收藏代码
  1. <dependency>  
  2.     <groupId>com.jolbox</groupId>  
  3.     <artifactId>bonecp</artifactId>  
  4.     <version>0.7.1.RELEASE</version>  
  5. </dependency>  

   下面配置系统日志,因为引入BoneCP而引入了slf4j,如果自动添加的版本过低,这里我们要重新设置slf4j的版本为1.6.4。那么我们添加logback来设置日志系统: 
Xml代码  收藏代码
  1. <dependency>  
  2.     <groupId>ch.qos.logback</groupId>  
  3.     <artifactId>logback-core</artifactId>  
  4.     <version>1.0.0</version>  
  5.     <type>jar</type>  
  6.     <scope>compile</scope>  
  7. </dependency>  
  8. <dependency>  
  9.     <groupId>ch.qos.logback</groupId>  
  10.     <artifactId>logback-classic</artifactId>  
  11.     <version>1.0.0</version>  
  12.     <type>jar</type>  
  13.     <scope>compile</scope>  
  14. </dependency>  

    下面配置logback.xml来配置日志具体项,logback.xml文件需要放置到类路径的根路径下: 
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <configuration>  
  3.     <jmxConfigurator />  
  4.     <!--输出到控制台,方便调试,应用时切换到文件Log -->  
  5.     <appender name="ConsoleAppender" class="ch.qos.logback.core.ConsoleAppender">  
  6.         <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">  
  7.             <pattern>%date %-5level [%logger{80}:%L] - %msg%n  
  8.             </pattern>  
  9.             <charset>UTF-8</charset>  
  10.         </encoder>  
  11.     </appender>  
  12.     <!-- 需要记录日志的包 -->  
  13.     <logger name="org.ourpioneer">  
  14.         <level value="debug" />  
  15.     </logger>  
  16.     <logger name="org.springframework">  
  17.         <level value="warn" />  
  18.     </logger>  
  19.     <root>  
  20.         <level value="warn" />  
  21.         <appender-ref ref="ConsoleAppender" />  
  22.     </root>  
  23. </configuration>  

    这里我们只创建了控制台的Appender,其中设置了日志的格式,编码和需要记录日志的包,并配置响应日志的级别,这都很好理解。下面是添加Spring和iBatis的类库: 
Xml代码  收藏代码
  1. <dependency>  
  2.     <groupId>org.apache.ibatis</groupId>  
  3.     <artifactId>ibatis-sqlmap</artifactId>  
  4.     <version>2.3.4.726</version>  
  5.     <scope>compile</scope>  
  6. </dependency>  

    Spring的类库添加core,beans,context,jdbc和orm模块即可,其它依赖则会自动添加过来,最终的类库如下图所示: 
 
    下面就是构建项目的目录结构: 
 
    我们采用分层开发的思想,DAO控制访问数据,Service调用DAO方法,同时在Service层做事务,因为我们不是Web项目,这里没有Web层的框架和Action。Bean包下的实体类Contact前面解释过了,common包下的BaseDAO提供操作iBatis的方法,ParameterMap是我们为iBatis提供参数的对象,dao包下就是DAO对象,service包下放置Service类,sqlMaps包下放置iBatis用到的SQL映射文件。App类是我们的测试类。类路径的根目录下的beans.xml是Spring的配置文件,logback.xml是日志配置文件,sqlMapConfig.xml是iBatis的总配置文件,首先来看sqlMapConfig.xml: 
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8" ?>   
  2. <!DOCTYPE sqlMapConfig   
  3.     PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"   
  4.     "http://www.ibatis.com/dtd/sql-map-config-2.dtd">  
  5. <sqlMapConfig>  
  6.     <settings cacheModelsEnabled="true" enhancementEnabled="true"  
  7.         lazyLoadingEnabled="true" errorTracingEnabled="true" maxRequests="32"  
  8.         maxSessions="10" maxTransactions="5" />  
  9.         <sqlMap resource="org/ourpioneer/contact/sqlMaps/contact.xml" />  
  10. </sqlMapConfig>  

    其中就是对iBatis的一些设置,并包含sqlMap文件,很简单,这没有什么可多说的,logback文件前面给出了,下面是Spring的配置文件,首先配置数据源dataSource: 
Xml代码  收藏代码
  1. <bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource"  
  2.     destroy-method="close">  
  3.     <property name="driverClass" value="com.mysql.jdbc.Driver" />  
  4.     <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test" />  
  5.     <property name="username" value="root" />  
  6.     <property name="password" value="123" />  
  7.     <property name="maxConnectionsPerPartition" value="30" />  
  8.     <property name="minConnectionsPerPartition" value="10" />  
  9.     <property name="partitionCount" value="3" />  
  10.     <property name="acquireIncrement" value="5" />  
  11.     <property name="statementsCacheSize" value="100" />  
  12.     <property name="releaseHelperThreads" value="3" />  
  13. </bean>  

    关于BoneCP的介绍网上也有很多,这里不再详细解释各个配置项的含义了,配置好数据源,下面是SqlMapClient,使用Spring的bean工厂来创建,参数是iBatis的总配置文件和数据源,这里我们需要注入配置好的数据源dataSource: 
Xml代码  收藏代码
  1. <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">  
  2.     <property name="configLocation" value="classpath:sqlMapConfig.xml" />  
  3.     <property name="dataSource" ref="dataSource" />  
  4. </bean>  

    Spring在对iBatis的支持上提供了SqlMapClientTemplate,也就是操作SqlMapClient的模板,这个jdbcTemplate类似,其中的方法使用方式也是类似的,为我们操作iBatis提供了便捷的接口: 
Xml代码  收藏代码
  1. <bean id="sqlMapClientTemplate" class="org.springframework.orm.ibatis.SqlMapClientTemplate">  
  2.         <constructor-arg>  
  3.             <ref bean="sqlMapClient" />  
  4.         </constructor-arg>  
  5.     </bean>  

    数据库操作的bean都配置好了,下面是事务模块的配置,我们抽象出Service层,也是为了方便事务操作,可能一组业务需要操作多个DAO,那么显然不能在DAO层做事务,而在业务层做事务是非常合适的,也符合逻辑,我们使用Spring提供的DataSourceTransactionManager来配置事务管理器: 
Xml代码  收藏代码
  1. <bean id="transactionManager"  
  2. class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
  3.     <property name="dataSource">  
  4.         <ref bean="dataSource" />  
  5.     </property>  
  6. </bean>  

    下面是事务拦截的方法和AOP切入点: 
Xml代码  收藏代码
  1. <tx:advice id="txAdvice" transaction-manager="transactionManager">  
  2.     <tx:attributes>  
  3.         <tx:method name="get*" read-only="true" />  
  4.         <tx:method name="insert*" rollback-for="Exception" />  
  5.         <tx:method name="add*" rollback-for="Exception" />  
  6.         <tx:method name="addOrUpdate*" rollback-for="Exception" />  
  7.         <tx:method name="del*" rollback-for="Exception" />  
  8.         <tx:method name="update*" rollback-for="Exception" />  
  9.     </tx:attributes>  
  10. </tx:advice>  
  11. <aop:config proxy-target-class="true">  
  12.     <aop:pointcut id="serviceMethod"  
  13.         expression="execution(* org.ourpioneer.service.*Service.*(..))" />  
  14.     <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />  
  15. </aop:config>  

这样,我们对org.ourpioneer.service.*Service中方法名以insert/add/del/update等开头的方法都做上事务了。因为我们使用Spring作为bean容器,那么将DAO和Service也纳入Spring 的管理之中: 
Xml代码  收藏代码
  1. <bean id="baseDAO" class="org.ourpioneer.contact.common.BaseDAO">  
  2.     <property name="sqlMapClientTemplate" ref="sqlMapClientTemplate" />  
  3. </bean>  
  4. <bean id="contactDAO" class="org.ourpioneer.contact.dao.impl.ContactDAOImpl"  
  5.     parent="baseDAO" />  

    这里我们将sqlMapClientTemplate配置到BaseDAO中,而ContactDAO继承BaseDAO即可,同时这里要注意这里我们使用了接口和实现相分离的做法,class中是实现类而不是接口,下面是Service: 
Xml代码  收藏代码
  1. <bean id="contactService" class="org.ourpioneer.contact.service.ContactService">  
  2.     <property name="contactDAO" ref="contactDAO" />  
  3. </bean>  

    配置文件都没有问题了,我们需要把这些涉及到的类都给写出来: 
Java代码  收藏代码
  1. package org.ourpioneer.contact.dao;  
  2. import java.util.Map;  
  3. import org.ourpioneer.contact.bean.Contact;  
  4. public interface ContactDAO {  
  5.     public Contact getContactById(Map<Object, Object> parameterMap);  
  6. }  

    DAO接口仅仅是方法的描述,而实现类中编写具体实现代码: 
Java代码  收藏代码
  1. package org.ourpioneer.contact.dao.impl;  
  2. import java.util.Map;  
  3. import org.ourpioneer.contact.bean.Contact;  
  4. import org.ourpioneer.contact.common.BaseDAO;  
  5. import org.ourpioneer.contact.dao.ContactDAO;  
  6. public class ContactDAOImpl extends BaseDAO implements ContactDAO {  
  7.     public Contact getContactById(Map<Object, Object> parameterMap) {  
  8.         return (Contact) getSqlMapClientTemplate().queryForObject("getContactById",  
  9.                 parameterMap);  
  10.     }  
  11. }  

    这里涉及到了BaseDAO,我们来看一下: 
Java代码  收藏代码
  1. package org.ourpioneer.contact.common;  
  2. import org.springframework.orm.ibatis.SqlMapClientTemplate;  
  3. public class BaseDAO {  
  4.     private SqlMapClientTemplate sqlMapClientTemplate;  
  5.     public SqlMapClientTemplate getSqlMapClientTemplate() {  
  6.         return sqlMapClientTemplate;  
  7.     }  
  8.     public void setSqlMapClientTemplate(  
  9.             SqlMapClientTemplate sqlMapClientTemplate) {  
  10.         this.sqlMapClientTemplate = sqlMapClientTemplate;  
  11.     }  
  12. }  

    调用DAO的Service代码如下: 
Java代码  收藏代码
  1. package org.ourpioneer.contact.service;  
  2. import java.util.Map;  
  3. import org.ourpioneer.contact.bean.Contact;  
  4. import org.ourpioneer.contact.common.ParameterMap;  
  5. import org.ourpioneer.contact.dao.ContactDAO;  
  6. public class ContactService {  
  7.     private ContactDAO contactDAO;  
  8.     public ContactDAO getContactDAO() {  
  9.         return contactDAO;  
  10.     }  
  11.     public void setContactDAO(ContactDAO contactDAO) {  
  12.         this.contactDAO = contactDAO;  
  13.     }  
  14.     public Contact getContactById(long id) {  
  15.         Map<Object, Object> parameterMap = new ParameterMap("ID", id);  
  16.         return getContactDAO().getContactById(parameterMap);  
  17.     }  
  18. }  

    从Spring的配置文件我们不难理解这些代码的真正含义,就不过多解释,这里用到了一个ParameterMap对象,我们来看一下它的定义: 
Java代码  收藏代码
  1. package org.ourpioneer.contact.common;  
  2. import java.util.HashMap;  
  3. public class ParameterMap extends HashMap<Object, Object> {  
  4.     private static final long serialVersionUID = 1L;  
  5.     public ParameterMap(Object... parameters) {  
  6.         for (int i = 0; i < parameters.length - 1; i += 2) {  
  7.             super.put(parameters[i], parameters[i + 1]);  
  8.         }  
  9.     }  
  10. }  

    非常的简单,这样我们在使用的时候就可以按照[名,值,名,值....]这样的格式来放置参数了。本例中涉及到了一个查询叫“getContactById”,它定义在sqlMaps下的contact.xml中,我们来看一下: 
Xml代码  收藏代码
  1. <?xml version="1.0" encoding="UTF-8" ?>  
  2. <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd" >  
  3. <sqlMap>  
  4.     <typeAlias alias="parameterMap" type="org.ourpioneer.contact.common.ParameterMap" />  
  5.     <typeAlias alias="contact" type="org.ourpioneer.contact.bean.Contact" />  
  6.     <select id="getContactById" parameterClass="parameterMap"  
  7.         resultClass="contact">  
  8.         select *  
  9.         from contact  
  10.         where ID=#ID:LONG#  
  11.     </select>  
  12. </sqlMap>  

    首先对ParameterMap和Contact进行别名,为了下面的方便调用,这里我们有一个查询,SQL语句很好理解,select元素的id属性就是它的标识符了,也是sqlMapClientTemplate的queryForObject方法第一个参数,parameterClass指定了参数类,我们使用的是自定义的ParameterMap,resultClass结果类型是我们的实体类对象,这样我们执行这个查询,iBatis会自动为我们封装成一个bean返回,易于调用。 
    为了测试,我们首先在数据表中插入一条记录: 
Sql代码  收藏代码
  1. INSERT INTO `contact` VALUES ('1''Sarin''male''15940912345''Dalian');  

    下面来编写测试代码: 
Java代码  收藏代码
  1. package org.ourpioneer.contact;  
  2. import org.ourpioneer.contact.bean.Contact;  
  3. import org.ourpioneer.contact.service.ContactService;  
  4. import org.slf4j.Logger;  
  5. import org.slf4j.LoggerFactory;  
  6. import org.springframework.context.ApplicationContext;  
  7. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  8. public class App {  
  9.     private static final Logger logger = LoggerFactory.getLogger(App.class);  
  10.     public static void main(String[] args) {  
  11.         ApplicationContext context = new ClassPathXmlApplicationContext(  
  12.                 "beans.xml");  
  13.         ContactService contactService = (ContactService) context  
  14.                 .getBean("contactService");  
  15.         Contact contact = contactService.getContactById(1);  
  16.         logger.info("{}",contact);  
  17.     }  
  18. }  

   我们从Spring的ApplicationContext中获取到Service对象,然后调用getContactById方法获取结果,下面是运行的结果: 
 
   下一篇我们将深入介绍使用SqlMapClientTemplate来操作iBatis进行数据库访问。
  • 查看图片附件
11 
1 
分享到:  
Spring数据库访问之iBatis(二) | HTML5/CSS3翻转动画(二)
  • 2012-01-02 18:45
  • 浏览 12359
  • 评论(2)
  • 分类:企业架构
  • 相关推荐
参考知识库
Hbase知识库4799  关注 | 63  收录
MongoDB知识库4098  关注 | 271  收录
区块链知识库2616  关注 | 90  收录
Objective-C知识库3851  关注 | 1209  收录
评论
2 楼 宋建勇 2012-05-31  
 nice ,但要是能给出完整代码下载就好了
1 楼 makemyownlife 2012-01-02  
  不错 加油:——
0 0
原创粉丝点击