mybatis使用心得

一、mybatis版本
个人建议使用:
			<dependency>
				<groupId>org.mybatis</groupId>
				<artifactId>mybatis</artifactId>
				<version>3.1.1</version>
			</dependency>

在mybatis3.1.1中优化了批量处理的效率
在底层statementHandle中提供了更加灵活的扩展性
主要是体现在插件,拦截器能做的,能够获取到的参数更多的方面

二、与spring集合的配置
	<bean id="sqlSessionFactory" 
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="datasource"></property>
		<property name="configLocation" value="classpath:context/mybatis-config.xml"></property>
		<property name="mapperLocations" value="classpath*:/com/tx/demo/**/*SqlMap.xml" />	
		<property name="typeHandlersPackage" value="com.tx.core.mybatis.handler"></property>
		<property name="failFast" value="true"></property>
		<property name="plugins">
			<array>
				<bean class="com.tx.core.mybatis.interceptor.PagedDiclectStatementHandlerInterceptor">
					<property name="dialect">
						<bean class="org.hibernate.dialect.PostgreSQLDialect"></bean>
					</property>
				</bean>
			</array>
		</property>
	</bean>
	
	<bean id="myBatisExceptionTranslator" class="org.mybatis.spring.MyBatisExceptionTranslator">
		<property name="dataSource">
			<ref bean="datasource"></ref>
		</property>
	</bean>

	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
		<constructor-arg name="executorType" ref="SIMPLE"></constructor-arg>
		<constructor-arg name="exceptionTranslator" ref="myBatisExceptionTranslator"></constructor-arg>
	</bean>
	
	<bean id="myBatisDaoSupport" class="com.tx.core.mybatis.support.MyBatisDaoSupport">
		<property name="sqlSessionTemplate">
			<ref bean="sqlSessionTemplate"/>
		</property>
	</bean>


这里对配置进行一下说明
mapperLocations: 通过正则表达式,支持mybatis动态扫描添加mapper不用像ibatis,用一个还要蛋疼滴添加一个include
typeHandlersPackage: 由于mybatis默认入参如果为空,又没有指定jdbcType时会抛出异常,在这里通过配置一些默认的类型空值插入的handle,以便处理mybatis的默认类型为空的情况
例如NullAbleStringTypeHandle通过实现当String字符串中为null是调用ps.setString(i,null)其他常用类型雷同
failFast:开启后将在启动时检查设定的parameterMap,resultMap是否存在,是否合法。个人建议设置为true,这样可以尽快定位解决问题。不然在调用过程中发现错误,会影响问题定位。

myBatisExceptionTranslator:用以支持spring的异常转换,通过配置该translatro可以将mybatis异常转换为spring中定义的DataAccessException

三、mybatis的批量处理功能,
由于在3.1.1升级后,可直接通过batchExcutor实现具体的批量执行。在该excutor中会重用上一次相同的prepareStatement。
具体实现这里贴一个:


    /**
     * 批量插入数据 <br/>
     * 1、数据批量插入,默认一次提交100条,当发生异常后继续提交异常行以后的数据,待集合全部进行提交后返回批量处理结果<br/>
     * 2、数据批量插入,如果需要回滚,当发生异常后,数据库异常即向外抛出,不会进行至全部执行后再抛出异常 <br/>
     * <功能详细描述>
     * 
     * @param statement
     * @param objectCollection
     * @param isRollback
     * @return [参数说明]
     * 
     * @return BatchResult<T> [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    public BatchResult batchInsert(String statement, List<?> objectList,
            boolean isStopWhenFlushHappenedException) {
        return batchInsert(statement,
                objectList,
                defaultDoFlushSize,
                isStopWhenFlushHappenedException);
    }
    
    /**
     * 批量插入数据
     * 
     * @param statement
     * @param objectList
     *            对象列表
     * @param doFlushSize
     * @param isStopWhenFlushHappenedException
     *            当在flush发生异常时是否停止,如果在调用insert时抛出的异常,不在此设置影响范围内
     * @return void [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
     */
    // 批量插入
    public BatchResult batchInsert(String statement, List<?> objectList,
            int doFlushSize, boolean isStopWhenFlushHappenedException) {
        BatchResult result = new BatchResult();
        if (CollectionUtils.isEmpty(objectList)) {
            return result;
        }
        if (doFlushSize <= 0) {
            doFlushSize = defaultDoFlushSize;
        }
        //设置总条数
        result.setTotalNum(objectList.size());
        
        //从当前环境中根据connection生成批量提交的sqlSession
        SqlSession sqlSession = this.sqlSessionTemplate.getSqlSessionFactory()
                .openSession(ExecutorType.BATCH);
        
        try {
            // 本次flush的列表开始行行索引
            int startFlushRowIndex = 0;
            for (int index = 0; index < objectList.size(); index++) {
                // 插入对象
                insertForBatch(sqlSession,
                        statement,
                        objectList.get(index),
                        null);
                if ((index > 0 && index % doFlushSize == 0)
                        || index == objectList.size() - 1) {
                    try {
                        List<org.apache.ibatis.executor.BatchResult> test = flushBatchStatements(sqlSession);
                        System.out.println(test);
                        startFlushRowIndex = index + 1;
                    }
                    catch (Exception ex) {
                        if (!(ex.getCause() instanceof BatchExecutorException)
                                || isStopWhenFlushHappenedException) {
                            DataAccessException translated = this.sqlSessionTemplate.getPersistenceExceptionTranslator()
                                    .translateExceptionIfPossible((PersistenceException) ex);
                            throw translated;
                        }
                        
                        BatchExecutorException e = (BatchExecutorException) ex.getCause();
                        // 如果为忽略错误异常则记录警告日志即可,无需打印堆栈,如果需要堆栈,需将日志级别配置为debug
                        logger.warn("batchInsert hanppend Exception:{},the exception be igorned.",
                                ex.toString());
                        if (logger.isDebugEnabled()) {
                            logger.debug(ex.toString(), ex);
                        }
                        
                        // 获取错误行数,由于错误行发生的地方
                        int errorRownumIndex = startFlushRowIndex
                                + e.getSuccessfulBatchResults().size();
                        result.addErrorInfoWhenException(objectList.get(index),
                                errorRownumIndex,
                                ex);
                        
                        //将行索引调整为错误行的行号,即从发生错误的行后面一行继续执行
                        index = errorRownumIndex;
                        startFlushRowIndex = errorRownumIndex + 1;
                    }
                }
            }
        }
        finally {
            sqlSession.close();
        }
        return result;
    }


这里的实现写得稍微复杂一些,
主要是,针对有些情况如果其中某条失败,还想后续数据能够继续成功提交的情况进行支持。

四、数据库物理分页,这个网上的文章也比较多,这里也提一下。在前人的基础上,我的物理分页类实现为:
<coding-3 lang="as">
/*
 * 描          述:  <描述>
 * 修  改   人:  PengQingyang
 * 修改时间:  2012-11-5
 * <修改描述:>
 */
package com.tx.core.mybatis.interceptor;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Properties;

import org.apache.ibatis.executor.statement.PreparedStatementHandler;
import org.apache.ibatis.executor.statement.RoutingStatementHandler;
import org.apache.ibatis.executor.statement.SimpleStatementHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.RowBounds;
import org.hibernate.dialect.Dialect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <数据库分页容器处理器>
 * <功能详细描述>
 * 
 * @author  PengQingyang
 * @version  [版本号, 2012-11-5]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }),
        @Signature(type = StatementHandler.class, method = "parameterize", args = { Statement.class }) })
public class PagedDiclectStatementHandlerInterceptor implements Interceptor {
    
    private Logger logger = LoggerFactory.getLogger(PagedDiclectStatementHandlerInterceptor.class);
    
    private Dialect dialect;
    
    /**
     * 物理分页插件拦截
     * @param invocation
     * @return
     * @throws Throwable
     */
    public Object intercept(Invocation invocation) throws Throwable {
        Method m = invocation.getMethod();
        if ("prepare".equals(m.getName())) {
            return prepare(invocation);
        } else if ("parameterize".equals(m.getName())) {
            return parameterize(invocation);
        }
        return invocation.proceed();
    }
    
    /**
     * @param target
     * @return
     */
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }
    
    /**
     * @param properties
     */
    public void setProperties(Properties properties) {
        
    }
    
    /**
      * 拦截prepare修改分页
      * <功能详细描述>
      * @param invocation
      * @return
      * @throws Throwable [参数说明]
      * 
      * @return Object [返回类型说明]
      * @exception throws [异常类型] [异常说明]
      * @see [类、类#方法、类#成员]
     */
    private Object prepare(Invocation invocation) throws Throwable {
        if (!(invocation.getTarget() instanceof RoutingStatementHandler)) {
            return invocation.proceed();
        }
        
        //提取statement
        RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation.getTarget();
        
        MetaObject metaStatementHandler = MetaObject.forObject(statementHandler);
        
        
        StatementHandler statement = (StatementHandler) metaStatementHandler.getValue("delegate");
        //如果不为两种statement则不继续进行处理
        if (!(statement instanceof SimpleStatementHandler)
                && !(statement instanceof PreparedStatementHandler)) {
            return invocation.proceed();
        }
        
        RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
        //根据rowBounds判断是否需要进行物理分页
        if (rowBounds == null
                || rowBounds.equals(RowBounds.DEFAULT)
                || (rowBounds.getOffset() <= RowBounds.NO_ROW_OFFSET && rowBounds.getLimit() == RowBounds.NO_ROW_LIMIT)) {
            return invocation.proceed();
        }
        
        //进行处理
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        String limitSql = dialect.getLimitString(sql,
                rowBounds.getOffset(),
                rowBounds.getLimit());
        
        if (statement instanceof SimpleStatementHandler) {
            limitSql.replaceAll("rownum <= ?", "rownum <= " + rowBounds.getLimit());
            limitSql.replaceAll("rownum_ > ?", "rownum_ > " + rowBounds.getOffset());
        }
        
        //如果为PreparedStatementHandler则无需替换即可
        metaStatementHandler.setValue("delegate.boundSql.sql",limitSql);
        
        if (logger.isDebugEnabled()) {
            logger.debug("生成分页SQL : " + boundSql.getSql());
        }
        
        return invocation.proceed();
    }
    
    /**
      * 设置分页参数
      * <功能详细描述>
      * @param invocation
      * @return
      * @throws Throwable [参数说明]
      * 
      * @return Object [返回类型说明]
      * @exception throws [异常类型] [异常说明]
      * @see [类、类#方法、类#成员]
     */
    private Object parameterize(Invocation invocation) throws Throwable {
        //先执行系统默认的参数设置
        Object returnObj = invocation.proceed();
        
        
        //提取statement
        RoutingStatementHandler routingStatementHandler = (RoutingStatementHandler) invocation.getTarget();
        MetaObject metaStatementHandler = MetaObject.forObject(routingStatementHandler);
        
        
        StatementHandler statementHandler = (StatementHandler) metaStatementHandler.getValue("delegate");
        //如果不为两种statement则不继续进行处理
        if (!(statementHandler instanceof PreparedStatementHandler)) {
            return returnObj;
        }
        
        RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
        //根据rowBounds判断是否需要进行物理分页
        if (rowBounds == null
                || rowBounds.equals(RowBounds.DEFAULT)
                || (rowBounds.getOffset() <= RowBounds.NO_ROW_OFFSET && rowBounds.getLimit() == RowBounds.NO_ROW_LIMIT)) {
            return returnObj;
        }
        
        //提取参数设置statement
        Statement statement = (Statement) invocation.getArgs()[0]; 
        if (!(statement instanceof PreparedStatement)) {  
            //如果对应statement不为PreparedStatement则直接返回
            return returnObj;
        }
        
        //设置分页的参数
        PreparedStatement ps = (PreparedStatement) statement;
        int parameterSize = statementHandler.getBoundSql().getParameterMappings().size();
        if(rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET 
                || rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT){
            ps.setInt(parameterSize + 1, rowBounds.getLimit());
            parameterSize++;
            if(rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET){
                ps.setInt(parameterSize + 1, rowBounds.getOffset());
            }
        }
        
        //替换rowBounds
        metaStatementHandler.setValue("delegate.rowBounds",
                RowBounds.DEFAULT);
        
        return returnObj;
    }
    
    /**
     * @return 返回 dialect
     */
    public Dialect getDialect() {
        return dialect;
    }
    
    /**
     * @param 对dialect进行赋值
     */
    public void setDialect(Dialect dialect) {
        this.dialect = dialect;
    }
}
</coding>


五、jpa注解的支持,mybatis本来优势就在于其sql可控,
个人不太倾向用太多的注解,mybatis的resultMap已经在ibatis基础上改进了很多,已经非常好用了,个人倾向于,利用表生成对应的model
然后根据实际业务将model改写,如需要oneToOne manyToOne时,添加jpa注解,调整bean属性命名后,根据model直接生成,dao,service,daoImpl,sqlMap,以及单元测试类
这个我现在有一个初步实现:
已经可以用了,大家可以一起使用一下,如果有问题,可以在这里回帖,我再进行逐步优化:
具体代码请在github上下载,建议使用eclipse版本为spring的sts
sqlMap后来考虑重用statemen有关null处已经进行调整,将于明天更新于github
有兴趣的可以从github下载相关代码:
https://github.com/txteam/tx-core/tree/1.0.x

这里贴一下自动生成的代码:
    public static void main(String[] args) throws Exception{
        JpaEntityFreeMarkerGenerator g = new JpaEntityFreeMarkerGenerator();
        
        g.generate(Demo.class, "d:/mybatis");
    }


<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper 
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="demo">

	<!-- auto generate default resultMap -->
	<resultMap id="demoMap" 
		type="com.tx.core.mybatis.data.Demo">
		<result column="subDemo_id" property="subDemo.id"/>
	</resultMap>
	
	<!-- auto generate default find -->
	<select id="findDemo" 
		parameterType="com.tx.core.mybatis.data.Demo"
		resultMap="demoMap">
		SELECT 
				TW.ID,
				TW.INTTEST,
				TW.BOOLEANTEST,
				TW.PASSOWRD,
				TW.ENDDATE,
				TW.ISBOOLEANOBJTEST,
				TW.LASTUPDATEDATE,
				TW.TESTBIGDECEIMAL,
				TW.INTEGERTEST,
				TW.EMAIL,
				TW.NEWNAME AS name,
				TW.SUBDEMO AS subDemo_id,
				TW.TESTINTEGER,
				TW.CREATEDATE
		  FROM WD_DEMO TW
		 WHERE
		<trim prefixOverrides="AND | OR">
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)">  
	            AND TW.ID = #{id}
	        </if>
		</trim>
	</select>
	
	<!-- auto generate default query -->
	<select id="queryDemo" 
		parameterType="com.tx.core.mybatis.data.Demo"
		resultMap="demoMap">
		SELECT 
				TW.ID,
				TW.INTTEST,
				TW.BOOLEANTEST,
				TW.PASSOWRD,
				TW.ENDDATE,
				TW.ISBOOLEANOBJTEST,
				TW.LASTUPDATEDATE,
				TW.TESTBIGDECEIMAL,
				TW.INTEGERTEST,
				TW.EMAIL,
				TW.NEWNAME AS name,
				TW.SUBDEMO AS subDemo_id,
				TW.TESTINTEGER,
				TW.CREATEDATE
		  FROM WD_DEMO TW
		<trim prefix="WHERE" prefixOverrides="AND | OR">
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)">  
	            AND TW.ID = #{id}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(intTest)">  
	            AND TW.INTTEST = #{intTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(booleanTest)">  
	            AND TW.BOOLEANTEST = #{booleanTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(passowrd)">  
	            AND TW.PASSOWRD = #{passowrd}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(endDate)">  
	            AND TW.ENDDATE = #{endDate}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(isBooleanObjTest)">  
	            AND TW.ISBOOLEANOBJTEST = #{isBooleanObjTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(lastUpdateDate)">  
	            AND TW.LASTUPDATEDATE = #{lastUpdateDate}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testBigDeceimal)">  
	            AND TW.TESTBIGDECEIMAL = #{testBigDeceimal}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(integerTest)">  
	            AND TW.INTEGERTEST = #{integerTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(email)">  
	            AND TW.EMAIL = #{email}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(name)">  
	            AND TW.NEWNAME = #{name}
	        </if>
			<if test="subDemo != null">
				<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(subDemo.id)">  
		            AND TW.SUBDEMO = #{subDemo.id}
		        </if>
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testInteger)">  
	            AND TW.TESTINTEGER = #{testInteger}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(createDate)">  
	            AND TW.CREATEDATE = #{createDate}
	        </if>
		</trim>
		<choose>  
	        <when test="@com.tx.core.util.OgnlUtils@isNotEmpty(orderSql)">  
	            ORDER BY #{orderSql}
	        </when>
	        <otherwise>  
	            <!-- //TODO:ADD DEFAULT ORDER COLUMN OR DONOTHING! -->
	        </otherwise>  
	    </choose>
	</select>
	
		<!-- auto generate default count -->
	<select id="queryDemoCount" 
		parameterType="com.tx.core.mybatis.data.Demo"
		resultType="java.lang.Integer">
		SELECT COUNT(1)
		  FROM WD_DEMO TW
		<trim prefix="WHERE" prefixOverrides="AND | OR">
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)">  
	            AND TW.ID = #{id}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(intTest)">  
	            AND TW.INTTEST = #{intTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(booleanTest)">  
	            AND TW.BOOLEANTEST = #{booleanTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(passowrd)">  
	            AND TW.PASSOWRD = #{passowrd}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(endDate)">  
	            AND TW.ENDDATE = #{endDate}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(isBooleanObjTest)">  
	            AND TW.ISBOOLEANOBJTEST = #{isBooleanObjTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(lastUpdateDate)">  
	            AND TW.LASTUPDATEDATE = #{lastUpdateDate}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testBigDeceimal)">  
	            AND TW.TESTBIGDECEIMAL = #{testBigDeceimal}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(integerTest)">  
	            AND TW.INTEGERTEST = #{integerTest}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(email)">  
	            AND TW.EMAIL = #{email}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(name)">  
	            AND TW.NEWNAME = #{name}
	        </if>
			<if test="subDemo != null">
				<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(subDemo.id)">  
		            AND TW.SUBDEMO = #{subDemo.id}
		        </if>
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(testInteger)">  
	            AND TW.TESTINTEGER = #{testInteger}
	        </if>
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(createDate)">  
	            AND TW.CREATEDATE = #{createDate}
	        </if>
		</trim>
	</select>
    
    <!-- auto generate default insert -->
    <insert id="insertDemo" 
		parameterType="com.tx.core.mybatis.data.Demo">
		INSERT INTO WD_DEMO
		(
			ID,
			INTTEST,
			BOOLEANTEST,
			PASSOWRD,
			ENDDATE,
			ISBOOLEANOBJTEST,
			LASTUPDATEDATE,
			TESTBIGDECEIMAL,
			INTEGERTEST,
			EMAIL,
			NEWNAME,
			SUBDEMO,
			TESTINTEGER,
			CREATEDATE
		)
		VALUES
		(
			#{id},
			#{intTest},
			#{booleanTest},
			#{passowrd},
			#{endDate},
			#{isBooleanObjTest},
			#{lastUpdateDate},
			#{testBigDeceimal},
			#{integerTest},
			#{email},
			#{name},
			<if test="subDemo != null">
				#{subDemo.id},
	        </if>
	        <if test="subDemo == null">
				#{subDemo,javaType=java.lang.String},
	        </if>
			#{testInteger},
			#{createDate}
		)
	</insert>
	
	<!-- auto generate default delete -->
	<delete id="deleteDemo" 
		parameterType="com.tx.core.mybatis.data.Demo">
		DELETE FROM WD_DEMO TW WHERE
		<trim prefixOverrides="AND | OR">
			<if test="@com.tx.core.util.OgnlUtils@isNotEmpty(id)">  
	            AND TW.ID = #{id}
	        </if>
		</trim>
	</delete>

	<!-- auto generate default update -->
	<update id="updateDemo"
	    parameterType="java.util.Map">  
	    UPDATE wd_demo TW
	    <trim prefix="SET" suffixOverrides=",">
			<if test="_parameter.containsKey('intTest')">
	    		INTTEST = #{intTest,javaType=int},
	    	</if>	
			<if test="_parameter.containsKey('booleanTest')">
	    		BOOLEANTEST = #{booleanTest,javaType=boolean},
	    	</if>	
			<if test="_parameter.containsKey('passowrd')">
	    		PASSOWRD = #{passowrd,javaType=java.lang.String},
	    	</if>	
			<if test="_parameter.containsKey('endDate')">
	    		ENDDATE = #{endDate,javaType=java.sql.Date},
	    	</if>	
			<if test="_parameter.containsKey('isBooleanObjTest')">
	    		ISBOOLEANOBJTEST = #{isBooleanObjTest,javaType=java.lang.Boolean},
	    	</if>	
			<if test="_parameter.containsKey('lastUpdateDate')">
	    		LASTUPDATEDATE = #{lastUpdateDate,javaType=java.sql.Timestamp},
	    	</if>	
			<if test="_parameter.containsKey('testBigDeceimal')">
	    		TESTBIGDECEIMAL = #{testBigDeceimal,javaType=java.math.BigDecimal},
	    	</if>	
			<if test="_parameter.containsKey('integerTest')">
	    		INTEGERTEST = #{integerTest,javaType=java.lang.Integer},
	    	</if>	
			<if test="_parameter.containsKey('email')">
	    		EMAIL = #{email,javaType=java.lang.String},
	    	</if>	
			<if test="_parameter.containsKey('name')">
	    		NEWNAME = #{name,javaType=java.lang.String},
	    	</if>	
			<if test="_parameter.containsKey('subDemo')">
				<if test="subDemo != null">
					SUBDEMO = #{subDemo.id,javaType=java.lang.String},
		        </if>
		        <if test="subDemo == null">
					SUBDEMO = #{subDemo,javaType=java.lang.String},
		        </if>
	    	</if>
			<if test="_parameter.containsKey('testInteger')">
	    		TESTINTEGER = #{testInteger,javaType=java.lang.Integer},
	    	</if>	
			<if test="_parameter.containsKey('createDate')">
	    		CREATEDATE = #{createDate,javaType=java.util.Date},
	    	</if>	
	    </trim>
	    WHERE TW.ID = #{id} 
	</update>  

</mapper>
<!--
sqlMap生成描述:

-->


/*
 * 描          述:  <描述>
 * 修  改   人:  
 * 修改时间:  
 * <修改描述:>
 */
package com.tx.core.mybatis.service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.tx.core.mybatis.dao.DemoDao;
import com.tx.core.mybatis.model.Demo;
import com.tx.core.exceptions.parameter.ParameterIsEmptyException;
import com.tx.core.paged.model.PagedList;

/**
 * Demo的业务层
 * <功能详细描述>
 * 
 * @author  
 * @version  [版本号, ]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@Component("demoService")
public class DemoService {
    
    @SuppressWarnings("unused")
    private Logger logger = LoggerFactory.getLogger(DemoService.class);
    
    @SuppressWarnings("unused")
    //@Resource(name = "serviceLogger")
    private Logger serviceLogger;
    
    @Resource(name = "demoDao")
    private DemoDao demoDao;
    
    /**
      * 根据Id查询Demo实体
      * 1、当id为empty时返回null
      * <功能详细描述>
      * @param id
      * @return [参数说明]
      * 
      * @return Demo [返回类型说明]
      * @exception throws 可能存在数据库访问异常DataAccessException
      * @see [类、类#方法、类#成员]
     */
    public Demo findDemoById(String id) {
        if (StringUtils.isEmpty(id)) {
            return null;
        }
        
        Demo condition = new Demo();
        condition.setId(id);
        return this.demoDao.findDemo(condition);
    }
    
    /**
      * 根据Demo实体列表
      * TODO:补充说明
      * 
      * <功能详细描述>
      * @return [参数说明]
      * 
      * @return List<Demo> [返回类型说明]
      * @exception throws [异常类型] [异常说明]
      * @see [类、类#方法、类#成员]
     */
    public List<Demo> queryDemoList(/*TODO:自己定义条件*/) {
        //TODO:判断条件合法性
        
        //TODO:生成查询条件
        Map<String, Object> params = new HashMap();
        
        //TODO:根据实际情况,填入排序字段等条件,根据是否需要排序,选择调用dao内方法
        List<Demo> resList = this.demoDao.queryDemoList(params);
        
        return resList;
    }
    
    /**
     * 分页查询Demo实体列表
     * TODO:补充说明
     * 
     * <功能详细描述>
     * @return [参数说明]
     * 
     * @return List<Demo> [返回类型说明]
     * @exception throws [异常类型] [异常说明]
     * @see [类、类#方法、类#成员]
    */
    public PagedList<Demo> queryDemoPagedList(/*TODO:自己定义条件*/int pageIndex,
            int pageSize) {
        //TODO:判断条件合法性
        
        //TODO:生成查询条件
        Map<String, Object> params = new HashMap<String, Object>();
        
        //TODO:根据实际情况,填入排序字段等条件,根据是否需要排序,选择调用dao内方法
        PagedList<Demo> resPagedList = this.demoDao.queryDemoPagedList(params, pageIndex, pageSize);
        
        return resPagedList;
    }
    
    /**
      * 查询demo列表总条数
      * TODO:补充说明
      * <功能详细描述>
      * @return [参数说明]
      * 
      * @return int [返回类型说明]
      * @exception throws [异常类型] [异常说明]
      * @see [类、类#方法、类#成员]
     */
    public int countDemo(/*TODO:自己定义条件*/){
        //TODO:判断条件合法性
        
        //TODO:生成查询条件
        Map<String, Object> params = new HashMap<String, Object>();
        
        //TODO:根据实际情况,填入排序字段等条件,根据是否需要排序,选择调用dao内方法
        int res = this.demoDao.countDemo(params);
        
        return res;
    }
    
    /**
      * 将demo实例插入数据库中保存
      * 1、如果demo为空时抛出参数为空异常
      * 2、如果demo中部分必要参数为非法值时抛出参数不合法异常
      * <功能详细描述>
      * @param demo [参数说明]
      * 
      * @return void [返回类型说明]
      * @exception throws 可能存在数据库访问异常DataAccessException
      * @see [类、类#方法、类#成员]
     */
    @Transactional
    public void insertDemo(Demo demo) {
        //TODO:验证参数是否合法,必填字段是否填写,
        //如果没有填写抛出parameterIsEmptyException,
        //如果有参数不合法ParameterIsInvalidException
        if (demo == null /*TODO:|| 其他参数验证*/) {
            throw new ParameterIsEmptyException(
                    "DemoService.insertDemo demo isNull.");
        }
        
        this.demoDao.insertDemo(demo);
    }
    
    /**
      * 根据id删除demo实例
      * 1、如果入参数为空,则抛出异常
      * 2、执行删除后,将返回数据库中被影响的条数
      * @param id
      * @return 返回删除的数据条数,<br/>
      * 有些业务场景,如果已经被别人删除同样也可以认为是成功的
      * 这里讲通用生成的业务层代码定义为返回影响的条数
      * @return int [返回类型说明]
      * @exception throws 可能存在数据库访问异常DataAccessException
      * @see [类、类#方法、类#成员]
     */
    @Transactional
    public int deleteById(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new ParameterIsEmptyException(
                    "DemoService.deleteById id isEmpty.");
        }
        
        Demo condition = new Demo();
        condition.setId(id);
        return this.demoDao.deleteDemo(condition);
    }
    
    /**
      * 根据id更新对象
      * <功能详细描述>
      * @param demo
      * @return [参数说明]
      * 
      * @return boolean [返回类型说明]
      * @exception throws [异常类型] [异常说明]
      * @see [类、类#方法、类#成员]
     */
    @Transactional
    public boolean updateById(Demo demo) {
        //TODO:验证参数是否合法,必填字段是否填写,
        //如果没有填写抛出parameterIsEmptyException,
        //如果有参数不合法ParameterIsInvalidException
        if (demo == null || StringUtils.isEmpty(demo.getId())) {
            throw new ParameterIsEmptyException(
                    "DemoService.updateById demo or demo.id is empty.");
        }
        
        //TODO:生成需要更新字段的hashMap
        Map<String, Object> updateRowMap = new HashMap<String, Object>();
        updateRowMap.put("id", demo.getId());
        
        //TODO:需要更新的字段
		updateRowMap.put("intTest", demo.getIntTest());	
		updateRowMap.put("booleanTest", demo.isBooleanTest());	
		updateRowMap.put("passowrd", demo.getPassowrd());	
		updateRowMap.put("endDate", demo.getEndDate());	
		updateRowMap.put("isBooleanObjTest", demo.getIsBooleanObjTest());	
		updateRowMap.put("lastUpdateDate", demo.getLastUpdateDate());	
		updateRowMap.put("testBigDeceimal", demo.getTestBigDeceimal());	
		updateRowMap.put("integerTest", demo.getIntegerTest());	
		updateRowMap.put("email", demo.getEmail());	
		updateRowMap.put("name", demo.getName());	
		//type:java.lang.String
		updateRowMap.put("subDemo", demo.getSubDemo());
		updateRowMap.put("testInteger", demo.getTestInteger());	
		updateRowMap.put("createDate", demo.getCreateDate());	
        
        int updateRowCount = this.demoDao.updateDemo(updateRowMap);
        
        //TODO:如果需要大于1时,抛出异常并回滚,需要在这里修改
        return updateRowCount >= 1;
    }
}



/*
 * 描          述:  <描述>
 * 修  改   人:  
 * 修改时间:  
 * <修改描述:>
 */
package com.tx.core.mybatis.dao.impl;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

import com.tx.core.mybatis.dao.DemoDao;
import com.tx.core.mybatis.data.Demo;
import com.tx.core.mybatis.model.Order;
import com.tx.core.mybatis.support.MyBatisDaoSupport;
import com.tx.core.paged.model.PagedList;

/**
 * Demo持久层
 * <功能详细描述>
 * 
 * @author  
 * @version  [版本号, 2012-12-11]
 * @see  [相关类/方法]
 * @since  [产品/模块版本]
 */
@Component("demoDao")
public class DemoDaoImpl implements DemoDao {
    
    @Resource(name = "myBatisDaoSupport")
    private MyBatisDaoSupport myBatisDaoSupport;
    
    /**
     * @param condition
     */
    @Override
    public void insertDemo(Demo condition) {
        this.myBatisDaoSupport.insertUseUUID("demo.insertDemo", condition, "id");
    }
    
    /**
     * @param condition
     * @return
     */
    @Override
    public int deleteDemo(Demo condition) {
        return this.myBatisDaoSupport.delete("demo.deleteDemo", condition);
    }
    
    /**
     * @param condition
     * @return
     */
    @Override
    public Demo findDemo(Demo condition) {
        return this.myBatisDaoSupport.<Demo> find("demo.findDemo", condition);
    }
    
    /**
     * @param params
     * @return
     */
    @Override
    public List<Demo> queryDemoList(Map<String, Object> params) {
        return this.myBatisDaoSupport.<Demo> queryList("demo.queryDemo",
                params);
    }
    
    /**
     * @param params
     * @param orderList
     * @return
     */
    @Override
    public List<Demo> queryDemoList(Map<String, Object> params,
            List<Order> orderList) {
        return this.myBatisDaoSupport.<Demo> queryList("demo.queryDemo",
                params,
                orderList);
    }
    
    /**
     * @param params
     * @return
     */
    @Override
    public int countDemo(Map<String, Object> params) {
        return this.myBatisDaoSupport.<Integer> find("demo.queryDemoCount",
                params);
    }
    
    /**
     * @param params
     * @param pageIndex
     * @param pageSize
     * @return
     */
    @Override
    public PagedList<Demo> queryDemoPagedList(Map<String, Object> params,
            int pageIndex, int pageSize) {
        return this.myBatisDaoSupport.<Demo> queryPagedList("demo.queryDemo",
                params,
                pageIndex,
                pageSize);
    }
    
    /**
     * @param params
     * @param pageIndex
     * @param pageSize
     * @param orderList
     * @return
     */
    @Override
    public PagedList<Demo> queryDemoPagedList(Map<String, Object> params,
            int pageIndex, int pageSize, List<Order> orderList) {
        return this.myBatisDaoSupport.<Demo> queryPagedList("demo.queryDemo",
                params,
                pageIndex,
                pageSize,
                orderList);
    }
    
    /**
     * @param updateRowMap
     * @return
     */
    @Override
    public int updateDemo(Map<String, Object> updateRowMap) {
        return this.myBatisDaoSupport.update("demo.updateDemo", updateRowMap);
    }
}

猜你喜欢

转载自p7engqingyang.iteye.com/blog/1746761