文档章节

iBatis开发详解(6)-----------Spring的数据库访问

Simon丶Ma
 Simon丶Ma
发布于 2016/04/14 14:55
字数 4330
阅读 0
收藏 0
点赞 1
评论 0
现在我们介绍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方法获取结果,下面是运行的结果: 



我们继续来研究Spring和iBatis的整合访问数据。下面首先来看看插入操作,数据的插入操作属于更新操作的一种,是比较简单的一种操作,就是将符合数据表字段规范且对应用程序无害的数据插入到数据表中。 
    我们分两种方式来进行插入操作,第一种是Bean的方式进行,首先来编写iBatis的插入SQL语句: 

Xml代码   收藏代码
  1. <insert id="insertContact" parameterClass="contact">  
  2.     insert into  
  3.     contact(NAME,GENDER,MOBILE,ADDRESS)  
  4.     values  
  5. (#name:VARCHAR#,#gender:VARCHAR#,#mobile:VARCHAR#,#address:VARCHAR#)  
  6. </insert>  

    我们使用<insert>标签表示插入语句,为该语句起个名字,就是id属性中的insertContact,之后声明我们使用的参数类型,也就是我们声明过的Contact。需要注意的是这里的参数设置,#name:VARCHAR#,小写的name是Bean中的字段名称,大小写要完全一致才行,VARCHAR表示的是数据类型,不用多说。在数据表中的这四个字段我们都声明为VARCHAR类型,而插入时不需要设置ID,是因为我们使用MySQL数据库的自增主键了,如果是其它类型的数据库,请使用相应的主键生成策略来为主键赋值。 
    编写完SQL语句,我们来写DAO: 
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.     public int insertContact(Contact contact);  
  7. }  

    我们多加了一个insertContact(Contact contact)方法,返回值类型是int,也就是更新的行数,这都是JDBC规范中的内容,下面来实现这个新加的方法: 
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(  
  9.                 "getContactById", parameterMap);  
  10.     }  
  11.     public int insertContact(Contact contact) {  
  12.         return getSqlMapClientTemplate().update("insertContact", contact);  
  13.     }  
  14. }  

    该方法的实现也非常简单,但是注意这里,我们并没有使用sqlMapClientTemplate的insert方法,而是update方法来进行操作的。原因是insert方法不会返回int类型的结果,而insert也是更新操作的一种,使用update方法也是可以的。下面在Service类中对应添加代码: 
Java代码   收藏代码
  1. public int insertContact(Contact contact) {  
  2.     return getContactDAO().insertContact(contact);  
  3. }  

    之后我们开始编写测试类,代码如下: 
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.         Contact contact = new Contact("Tom""male""15940990001""Dalian");  
  17.         int recordsOfUpdates = contactService.insertContact(contact);  
  18.         logger.info("{}", recordsOfUpdates);  
  19.     }  
  20. }  

    这里需要注意,我们创建Bean时使用了带有参数的构造方法(且不含ID),那么还需要在Contact类中声明出无参数的构造方法,也就是在Contact类中添加如下两个构造方法: 
Java代码   收藏代码
  1. public Contact() {  
  2.     super();  
  3. }  
  4. public Contact(String name, String gender, String mobile, String address) {  
  5.     super();  
  6.     this.name = name;  
  7.     this.gender = gender;  
  8.     this.mobile = mobile;  
  9.     this.address = address;  
  10. }  

    运行测试程序,我们会得到如下输出: 
 
    可以看出update语句的返回值是1,也就是说我们成功地更新了一行数据,打开数据表,我们可以看到这条数据已经成功添加进去了: 
 
    下面来看第二种参数设置方式,就是使用我们之前的ParameterMap方式。使用Bean是ORM特性的体现,而如果在一个事务中,需要向多个表中插入数据,显然使用Bean的方式存在不足,因为中间表可能没有对应的Bean存在,而且构造Bean是消耗系统资源的,特别是在批量操作时,是不建议使用Bean的方式的。那么我们可以使用ParameterMap的方式来统一设置传入参数。 
     修改SQL语句: 
Xml代码   收藏代码
  1. <insert id="insertContact" parameterClass="parameterMap">  
  2.     insert into  
  3.     contact(NAME,GENDER,MOBILE,ADDRESS)  
  4.     values  
  5. (#NAME:VARCHAR#,#GENDER:VARCHAR#,#MOBILE:VARCHAR#,#ADDRESS:VARCHAR#)  
  6. </insert>  

    之后在DAO中重载一个insertContact方法: 
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.     public int insertContact(Contact contact);  
  7.     public int insertContact(Map<Object, Object> parameterMap);  
  8. }  

    然后编写实现代码: 
Java代码   收藏代码
  1. public int insertContact(Map<Object, Object> parameterMap) {  
  2.         return getSqlMapClientTemplate().update("insertContact", parameterMap);  
  3.     }  

    和之前的完全类似,只是参数不同,就是重载了一个方法而已。下面是Service方法: 
Java代码   收藏代码
  1. public int insertContact(String name, String gender, String mobile,  
  2.         String address) {  
  3.     Map<Object, Object> parameterMap = new ParameterMap("NAME", name,  
  4.             "GENDER", gender, "MOBILE", mobile, "ADDRESS", address);  
  5.     return getContactDAO().insertContact(parameterMap);  
  6. }  

    这里我们将传入的四个参数重新构造成一个ParameterMap类型的变量,为什么要在Service中完成这步操作,就是出于事务捆绑的操作。在Service层我们将操作视为一个具体的业务,那么它可能向下要调用多个DAO来向不同数据表进行操作,那么在这层构造数据调用各自的DAO完成SQL操作是最合理的,所以我们将数据的构造操作放在了Service层来进行,之后重新改写测试代码: 
Java代码   收藏代码
  1. package org.ourpioneer.contact;  
  2. import org.ourpioneer.contact.service.ContactService;  
  3. import org.slf4j.Logger;  
  4. import org.slf4j.LoggerFactory;  
  5. import org.springframework.context.ApplicationContext;  
  6. import org.springframework.context.support.ClassPathXmlApplicationContext;  
  7. public class App {  
  8.     private static final Logger logger = LoggerFactory.getLogger(App.class);  
  9.     public static void main(String[] args) {  
  10.         ApplicationContext context = new ClassPathXmlApplicationContext(  
  11.                 "beans.xml");  
  12.         ContactService contactService = (ContactService) context  
  13.                 .getBean("contactService");  
  14.         // Contact contact = contactService.getContactById(1);  
  15.         // Contact contact = new Contact("Tom", "male", "15940990001",  
  16.         // "Dalian");  
  17.         int recordsOfUpdates = contactService.insertContact("Tom""male","15940990001""Dalian");  
  18.         logger.info("{}", recordsOfUpdates);  
  19.     }  
  20. }  

    我们仍然得到了更新一行数据的结果,可以看到数据库中就又多了一条数据。 
     下面是数据更新操作,也就是SQL的update操作,还是先来编写SQL语句: 
Xml代码   收藏代码
  1. <update id="updateContactById" parameterClass="contact">  
  2.     update contact   
  3.     set NAME=#name:VARCHAR#,GENDER=#gender:VARCHAR#,MOBILE=#mobile:VARCHAR#,ADDRESS=#address:VARCHAR#  
  4.     where ID=#id:LONG#  
  5. </update>  

    可以看出,这里也是使用Bean的方式来进行更新,那么DAO代码如下: 
Java代码   收藏代码
  1. public int updateContactById(Contact contact) {  
  2.     return getSqlMapClientTemplate().update("updateContactById", contact);  
  3. }  

    然后是Service代码: 
Java代码   收藏代码
  1. public int updateContact(Contact contact) {  
  2.     return getContactDAO().updateContactById(contact);  
  3. }  

    而测试时,我们是先将一条记录给查出来,之后更改几个属性,再给更新数据,那么测试代码为: 
Java代码   收藏代码
  1. public class App {  
  2.     private static final Logger logger = LoggerFactory.getLogger(App.class);  
  3.     public static void main(String[] args) {  
  4.         ApplicationContext context = new ClassPathXmlApplicationContext(  
  5.                 "beans.xml");  
  6.         ContactService contactService = (ContactService) context  
  7.                 .getBean("contactService");  
  8.         Contact contact = contactService.getContactById(2);  
  9.         System.out.println(contact);  
  10.         contact.setMobile("15900000001");  
  11.         contact.setAddress("Beijing");  
  12.         int recordsOfUpdates = contactService.updateContact(contact);  
  13.         logger.info("{}", recordsOfUpdates);  
  14.     }  

    运行测试代码,我们得到如下结果: 
 
    之后查看数据库,发现ID为2的记录已经更改了: 
 
    和插入操作一样,我们还可以使用ParameterMap的方式来实现更新,应用场景也是和前面类似的。这里就不再给出演示了,直接看最后一个操作,就是删除操作。删除应该是最简单的一种操作了,我们编写一个SQL: 
Xml代码   收藏代码
  1. <delete id="deleteContactById" parameterClass="parameterMap">  
  2.     delete from contact where ID=#ID:LONG#  
  3. </delete>  

    我们使用的是parameterMap作为传入的参数类型,那么DAO代码如下: 
Java代码   收藏代码
  1. public int deleteContactById(Map<Object, Object> parameterMap) {  
  2.     return getSqlMapClientTemplate().update("deleteContactById", parameterMap);  
  3. }  

    在Service中,我们构造出parameerMap对象: 
Java代码   收藏代码
  1. public int deleteContactById(long id) {  
  2.     Map<Object, Object> parameterMap = new ParameterMap("ID", id);  
  3.     return getContactDAO().deleteContactById(parameterMap);  
  4. }  

下面是测试代码,我们直接指定要删除的记录ID即可: 
Java代码   收藏代码
  1. public class App {  
  2.     private static final Logger logger = LoggerFactory.getLogger(App.class);  
  3.   
  4.     public static void main(String[] args) {  
  5.         ApplicationContext context = new ClassPathXmlApplicationContext(  
  6.                 "beans.xml");  
  7.         ContactService contactService = (ContactService) context  
  8.                 .getBean("contactService");  
  9.         int recordsOfUpdates = contactService.deleteContactById(3);  
  10.         logger.info("{}", recordsOfUpdates);  
  11.     }  
  12. }  

    运行测试代码,我们可以看到成功更新了一条记录,也就是将第三条记录删除,那么再看看数据库,也就只有两条记录了。 
    本部分内容也就全部介绍完了。

© 著作权归作者所有

共有 人打赏支持
Simon丶Ma
粉丝 4
博文 134
码字总数 299850
作品 0
深圳
程序员
ibatis MyBatis区别与联系

简介: 本文主要讲述了 iBatis 2.x 和 MyBatis 3.0.x 的区别,以及从 iBatis 向 MyBatis 移植时需要注意的地方。通过对本文的学习,读者基本能够了解 MyBatis 有哪些方面的改进,并能够顺利使...

为了美好的明天 ⋅ 04/17 ⋅ 0

00fly/springmvc_ibatis_plus

#springmvcibatisplus ** 针对ibatis框架的代码生成器项目不再维护了,sorry。。。 ** 说明:如果数据库表中oracle无blob,clob字段,mysql中无text,blob字段请使用 noSupportBCLOB 分支代码...

00fly ⋅ 06/01 ⋅ 0

ibatis sqlMap 使用

SqlMap的配置是iBatis中应用的核心。这部分任务占据了iBatis开发的70的工作量。 1、命名空间: 在此空间外要引用此空间的元素,则需要加上命名空间名。 2、实体的别名: 如果有用到的全名的地...

为了美好的明天 ⋅ 04/27 ⋅ 0

阿里,百度,腾讯等一线互联网公司中,Java开发的招聘标准

金三银四的跳槽热潮即将过去,在这两个月的跳槽的旺季中,作为互联网行业的三大巨头,百度、阿里巴巴、腾讯对于互联网人才有很大的吸引力,他们的员工也是众多互联网同行觊觎的资深工程师、管...

javaxuexi123 ⋅ 04/20 ⋅ 0

MyBatis3-SqlSessionDaoSupport的使用

以下内容引用自http://www.yihaomen.com/article/java/336.htm: 在MyBatis3中这个Mapper接口貌似充当了以前在iBatis2中的DAO层的作用。但事实上,如果有这个Mapper接口不能完成的工作,或者...

easonjim ⋅ 2017/06/22 ⋅ 0

OceanBase的正确使用方法

OceanBase不是设计出来的,而是在使用过程中不断进化出来的。因此,系统使用以及运维的方便性至关重要。 OceanBase的使用者是业务系统开发人员,并交由专门的OceanBase DBA来运维。为了方便业...

凌洛 ⋅ 05/19 ⋅ 0

Mybatis中Mapper映射文件详解

紧接上文所述,在这篇文章中我将对Mapper映射文件进行详细的说明。 Mapper映射文件是一个xml格式文件,必须遵循相应的dtd文件规范,如ibatis-3-mapper.dtd。我们先大体上看看支持哪些配置?如...

u012843873 ⋅ 05/04 ⋅ 0

MyBatis在注解上使用动态SQL(@select使用if)

1、用标签包围,然后像xml语法一样书写 @Select({"

easonjim ⋅ 2017/08/29 ⋅ 0

Spring MVC 到 Spring BOOT的简化之路

背景 从Servlet技术到Spring和Spring MVC,开发Web应用变得越来越简捷。但是Spring和Spring MVC的众多配置有时却让人望而却步,相信有过Spring MVC开发经验的朋友能深刻体会到这一痛苦。因为...

临江仙卜算子 ⋅ 05/09 ⋅ 0

成为Java高手的25个学习目标

你已经掌握了这25条中的多少条了呢? 1.你需要精通面向对象分析与设计(OOA/OOD)、涉及模式(GOF,J2EEDP)以及综合模式。你应该了解UML,尤其是 class,object,interaction以及statediag...

thinkyoung ⋅ 2014/11/01 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

浅谈springboot Web模式下的线程安全问题

我们在@RestController下,一般都是@AutoWired一些Service,由于这些Service都是单例,所以并不存在线程安全问题。 由于Controller本身是单例模式 (非线程安全的), 这意味着每个request过来,...

算法之名 ⋅ 今天 ⋅ 0

知乎Java数据结构

作者:匿名用户 链接:https://www.zhihu.com/question/35947829/answer/66113038 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 感觉知乎上嘲讽题主简...

颖伙虫 ⋅ 今天 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部