• MyBatis(十一):Mybatis 动态SQL语句完成多条件查询


    之前文章中对in的用法做过讲解:《MyBatis(四):mybatis中使用in查询时的注意事项

    实际上对于多个参数的用法也是这是注意的:

    多参&if判空&List集合判空&in用法

        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @Select(value = {
                "<script>",
                " SELECT  `id`,`title` ",
                " FROM `tb_article` ",
                " WHERE `category_id`=#{article.categoryId} ",
                "   <if test='article.status!=null'>",
                "   AND `status` = #{article.status} ",
                "   </if>",
                "   <if test='typeList!=null and !typeList.isEmpty()'>",
                "       and `article_type` in",
                "        <foreach collection="typeList" index="index" item="item" open="(" separator="," close=")">",
                "           #{item} ",
                "        </foreach>",
                "   </if>",
                "</script>"
                })
        @ResultMap(value = {"articleResultMap"})
        List<ArticlePo> queryByCondition(final @Param("article") ArticleModel article, final @Param("typeList") List<Integer> typeList);

    1)上边主要对普通参数判断空用法:<if test='article.status!=null'>

    2)集合判空的用法:<if test='typeList!=null and !typeList.isEmpty()'>

    3)in的用法:<foreach collection="typeList" index="index" item="item" open="(" separator="," close=")">";

    4)多参数用法,实际上多个参数如果使用@SqlProvider方式是,在ArticleSqlProvider的类中方法中接收的参数对象为Map<String,Object>,该map集合中包含两个对象:key:article的ArticleModel对象;key:typeList的List<Integer>对象。获取方式:ArticleModel aritlce=(ArticleModel)map.get("aritcle");List<Integer> typeList=(List<Integer>)map.get("typeList");。

    Mybatis使用POJO传递参数:

            @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
            @ResultMap("logResult")
            @Select(value={ 
                    "<script>",
                    "select * from `log` " ,
                    "<where>" ,
                    "     <if test="title!=null and title!=''">" ,
                    "          and `title` like CONCAT('%', #{title}, '%') " , 
                    "     </if>" ,
                    "     <if test="moduleType!=null ">" , 
                    "          and `module_type`=#{moduleType} " , 
                    "     </if>" , 
                    "     <if test="operateType!=null ">" , 
                    "          and `operate_type`=#{operateType} " , 
                    "     </if>" , 
                    "</where>",
                    "</script>"
                    })
            List<Log> getByPojo(Log log);

    src/main/resources/mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!-- 引用db.properties配置文件 -->
        <properties resource="jdbc.properties"/>
        <!--配置全局属性-->
        <settings>
            <!-- 打开延迟加载的开关 -->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!-- 将积极加载改为消极加载(即按需加载) -->
            <setting name="aggressiveLazyLoading" value="false"/>
            <!-- 打开全局缓存开关(二级缓存)默认值就是 true -->
            <setting name="cacheEnabled" value="true"/>
            <!--使用jdbc的getGeneratekeys获取自增主键值-->
            <setting name="useGeneratedKeys" value="true"/>
            <!--使用列别名替换别名  默认true select name as title form table; -->
            <setting name="useColumnLabel" value="true"/>
            <!--开启驼峰命名转换-->
            <setting name="mapUnderscoreToCamelCase" value="true"/>
            <!--打印sql日志-->
            <setting name="logImpl" value="STDOUT_LOGGING" />
        </settings>
        <typeAliases>
            <package name="com.dx.test.model"/>
        </typeAliases>
        <!-- 
        元素类型为 "configuration" 的内容必须匹配 "
        (properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,
          plugins?,environments?,databaseIdProvider?,mappers?)"。
       -->
        <typeHandlers>
            <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.dx.test.model.enums.ModuleType"/>
            <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.dx.test.model.enums.OperateType"/>
        </typeHandlers>
        <!-- 对事务的管理和连接池的配置 -->
        <environments default="mysql_jdbc">
            <environment id="mysql_jdbc">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${name}"/>
                    <property name="password" value="${password}"/>
                </dataSource>
            </environment>
        </environments>
        <!--
        <mappers>
            <mapper resource="resources/mapper/LogMapper.xml"/>
        </mappers>
        -->
        <mappers>
            <mapper class="com.dx.test.dao.LogMapper"></mapper>
        </mappers>
    </configuration>
    View Code

    src/main/resources/log.properties

    log4j.rootLogger=DEBUG, Console
    #Console
    log4j.appender.Console=org.apache.log4j.ConsoleAppender
    log4j.appender.Console.layout=org.apache.log4j.PatternLayout
    log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
    log4j.logger.java.sql.ResultSet=INFO
    log4j.logger.org.apache=INFO
    log4j.logger.java.sql.Connection=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    View Code

    src/main/resources/jdbc.properties

    driver=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false
    name=root
    password=123456
    View Code

    pom.xml

            <!--MyBatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.6</version>
            </dependency>
            <!--MySql数据库驱动 -->
            <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.21</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.11</version>
            </dependency>
            
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>
    View Code

    LogMapper.java(Mybatis mapper类)

    package com.dx.test.dao; 
    
    import java.util.List;
    import java.util.Map;
    
    import org.apache.ibatis.annotations.InsertProvider;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Options;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Result;
    import org.apache.ibatis.annotations.ResultMap;
    import org.apache.ibatis.annotations.Results;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    
    import com.dx.test.dao.sqlprovider.LogSqlProvider;
    import com.dx.test.model.Log;
    import com.dx.test.model.enums.ModuleType;
    import com.dx.test.model.enums.OperateType;
    
    @Mapper
    public interface LogMapper {
        /**
         * 入库日志
         * 
         * @param log 待入库实体
         * @return 影响条数
         */
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.TRUE, useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
        @InsertProvider(type = LogSqlProvider.class, method = "insert")
        public int insert(Log log);
    
        /**
         * 根据文章id,查询日志详情
         * 
         * @param id 日志id
         * @return 返回查询到的日志详情
         */
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @Results(id = "logResult", value = { 
                @Result(property = "id", column = "id", id = true),
                @Result(property = "title", column = "title"), 
                @Result(property = "content", column = "content"),
                @Result(property = "moduleType", column = "module_type", javaType = ModuleType.class),
                @Result(property = "operateType", column = "operate_type", javaType = OperateType.class),
                @Result(property = "dataId", column = "data_id"),
                @Result(property = "createUser", column = "create_user"),
                @Result(property = "createUserId", column = "create_user_id"),
                @Result(property = "createTime", column = "create_time")
                })
        @Select({ "select * from `log` where `id`=#{id}" })
        Log getById(@Param("id") Long id);
        
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @ResultMap("logResult")
        @Select(value={ 
            "<script>",
            "select * from `log` " ,
            "<where>" ,
            "     <if test="title!=null and title!=''">" ,
            "          and `title` like CONCAT('%', #{title}, '%') " , 
            "     </if>" ,
            "     <if test="moduleType!=null ">" , 
            "          and `module_type`=#{moduleType} " , 
            "     </if>" , 
            "     <if test="operateType!=null ">" , 
            "          and `operate_type`=#{operateType} " , 
            "     </if>" , 
            " </where>",
            "</script>"
            })
        List<Log> getByPojo(Log log);
        
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @ResultMap("logResult")
        @Select(value={ 
                "<script>",
                "select * from `log` " ,
                "<where>" ,
                "     <if test="title!=null and title!=''">" ,
                "          and `title` like CONCAT('%', #{title}, '%') " , 
                "     </if>" ,
                "     <if test="moduleType!=null ">" , 
                "          and `module_type`=#{moduleType} " , 
                "     </if>" , 
                "     <if test="operateType!=null ">" , 
                "          and `operate_type`=#{operateType} " , 
                "     </if>" , 
                " </where>",
                "</script>"
                })
        List<Log>  getByParameter(@Param("title") String title,@Param("moduleType") ModuleType moduleType,@Param("operateType") OperateType operateType);
        
    
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @ResultMap("logResult")
        @Select(value={ 
                "<script>",
                "select * from `log` " ,
                "<where>" ,
                "     <if test="title!=null and title!=''">" ,
                "          and `title` like CONCAT('%', #{title}, '%') " , 
                "     </if>" ,
                "     <if test="moduleType!=null ">" , 
                "          and `module_type`=#{moduleType} " , 
                "     </if>" , 
                "     <if test="operateType!=null ">" , 
                "          and `operate_type`=#{operateType} " , 
                "     </if>" , 
                " </where>",
                "</script>"
                })
        List<Log> getByMap(Map<String, Object> map);
    
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @ResultMap("logResult")
        @Select({ 
            "<script>",
            "select * from `log` " ,
            "<where>" ,
            "    <choose> ",
            "        <when test="dataId!=null">",
            "            and data_id=#{dataId}",
            "        </when>",
            "        <when test="id!=null">",
            "            and id=#{id}",
            "        </when>",
            "        <otherwise>",
            "            and 1=1",
            "        </otherwise>",
            "    </choose>",
            "</where>" ,
            "</script>"})
        List<Log> getList(final Log log);
    
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.TRUE)
        @Update({ 
            "<script>",
            "update `log` " ,
            "<set>" ,
            "    <if test="dataId!=null">",
            "        `data_id`=#{dataId},",
            "    </if>",
            "    <if test="title!=null">",
            "        `title`=#{title},",
            "    </if>",
            "    <if test="content!=null">",
            "        `content`=#{content} ",
            "    </if>",
            "</set>" ,
            " where id=#{id}",
            "</script>"})
        int update(final Log log);
        
        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @ResultMap("logResult")
        @Select({ "select * from `log` where `id`<#{log.id}" })
        List<Log> getListWithPager(@Param("log")Log log,@Param("pageNum") int pageNum,@Param("pageSize") int pageSize);
    }
    View Code

    LogSqlProvider.java(LogMapper中使用sql代理类)

    public class LogSqlProvider {
        /**
         * 生成插入日志SQL
         * @param log 日志实体
         * @return 插入日志SQL
         * */
        public String insert(Log log) {
            return new SQL() {
                {
                    INSERT_INTO("log");
                    INTO_COLUMNS("title", "module_type", "operate_type","data_id", "content", "create_time","create_user","create_user_id");
                    INTO_VALUES("#{title}", "#{moduleType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}", "#{operateType,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}","#{dataId}", "#{content}", "now()","#{createUser}","#{createUserId}");
                }
            }.toString();
        }
    }
    View Code

    ModuleType.java(enum)

    package com.dx.test.model.enums;
    
    public enum ModuleType {
        Unkown(0),
        /**
         * 文章模块
         */
        Article_Module(1),
        /**
         * 文章分类模块
         **/
        Article_Category_Module(2),
        /**
         * 配置模块
         */
        Settings_Module(3);
        
        private int value;
    
        ModuleType(int value) {
            this.value = value;
        }
    
        public int getValue() {
            return this.value;
        }
    }
    View Code

    OperateType.java(enum)

    package com.dx.test.model.enums;
    
    public enum OperateType {
        /**
         * 如果0未占位,可能会出现错误。
         * */
        Unkown(0),
        /**
         * 新增
         */
        Create(1),
        /**
         * 修改
         */
        Modify(2),
        /**
         * 删除
         */
        Delete(3),
        /**
         * 查看
         */
        View(4),
        /**
         * 作废
         */
        UnUsed(5);
    
        private int value;
    
        OperateType(int value) {
            this.value = value;
        }
    
        public int getValue() {
            return this.value;
        }
    }
    View Code

    Log.java(实体类)

    package com.dx.test.model;
    
    import java.util.Date;
    
    import com.dx.test.model.enums.ModuleType;
    import com.dx.test.model.enums.OperateType;
     
    public class Log {
        private Long id; // 自增id
        private String title;// 日志msg
        private ModuleType moduleType;// 日志归属模块
        private OperateType operateType; // 日志操作类型
        private String dataId; // 操作数据id
        private String content; // 日志内容简介
        private Date createTime; // 新增时间
        private String createUser; // 新增人
        private String createUserId; // 新增人id
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public ModuleType getModuleType() {
            return moduleType;
        }
    
        public void setModuleType(ModuleType moduleType) {
            this.moduleType = moduleType;
        }
    
        public OperateType getOperateType() {
            return operateType;
        }
    
        public void setOperateType(OperateType operateType) {
            this.operateType = operateType;
        }
    
        public String getDataId() {
            return dataId;
        }
    
        public void setDataId(String dataId) {
            this.dataId = dataId;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public Date getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    
        public String getCreateUser() {
            return createUser;
        }
    
        public void setCreateUser(String createUser) {
            this.createUser = createUser;
        }
    
        public String getCreateUserId() {
            return createUserId;
        }
    
        public void setCreateUserId(String createUserId) {
            this.createUserId = createUserId;
        }
    
        @Override
        public String toString() {
            return "Log [id=" + id + ", title=" + title + ", moduleType=" + moduleType + ", operateType=" + operateType
                    + ", dataId=" + dataId + ", content=" + content + ", createTime=" + createTime + ", createUser="
                    + createUser + ", createUserId=" + createUserId + "]";
        }
    
    }
    View Code

    MybatisTest.java(测试入口类)

    package com.dx.test;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.io.IOException;
    import java.io.InputStream;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import com.dx.test.dao.LogMapper;
    import com.dx.test.model.Log;
    import com.dx.test.model.enums.ModuleType;
    import com.dx.test.model.enums.OperateType;
    
    public class MybatisTest {
        public static void main(String[] args) {
            InputStream config = null;
            try {
                config = Resources.getResourceAsStream("mybatis-config.xml");
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
    
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(config);
            SqlSession sqlSession = sqlSessionFactory.openSession();
            LogMapper logMapper = sqlSession.getMapper(LogMapper.class);
            
            // choose:
            Log queryLog= new Log();
            queryLog.setDataId("1");
            List<Log> logByDataIdList=logMapper.getList(queryLog);
            for (Log item : logByDataIdList) {
                System.out.println(item);
            }
            
            System.out.println("==========================================================");
            String[] titleList = new String[] { "test", "test2", "awr", "a", "c", "tes", "ll", "gg", "dd", "22" };
            ModuleType[] moduleTypes = new ModuleType[] { ModuleType.Article_Category_Module, ModuleType.Article_Module,ModuleType.Settings_Module };
            OperateType[] operateTypes = new OperateType[] { OperateType.Create, OperateType.Delete, OperateType.Modify,OperateType.Modify, OperateType.UnUsed };
            for (int i = 0; i < 10; i++) {
                Log waitingInsertLog = new Log();
    
                waitingInsertLog.setTitle("log " + titleList[i]);
                waitingInsertLog.setContent("test content" + titleList[i]);
                waitingInsertLog.setCreateTime(new Date());
                waitingInsertLog.setCreateUser("test user");
                waitingInsertLog.setCreateUserId("test user id");
                waitingInsertLog.setDataId(String.valueOf(i + 100));
                waitingInsertLog.setModuleType(moduleTypes[i % 3]);
                waitingInsertLog.setOperateType(operateTypes[i % 5]);
                int newLogId = logMapper.insert(waitingInsertLog);
                System.out.println(waitingInsertLog.getId());
            }
    
            // set: 测试
            System.out.println("=========================================");
            Log waitingInsertLog = new Log();
    
            waitingInsertLog.setTitle("log");
            waitingInsertLog.setContent("test content");
            waitingInsertLog.setCreateTime(new Date());
            waitingInsertLog.setCreateUser("test user");
            waitingInsertLog.setCreateUserId("test user id");
            waitingInsertLog.setDataId("9999");
            waitingInsertLog.setModuleType(ModuleType.Article_Module);
            waitingInsertLog.setOperateType(OperateType.View);
            int newLogId = logMapper.insert(waitingInsertLog);
    
            System.out.println("insert result:"+logMapper.getById(waitingInsertLog.getId()));
            
            Log waitingUpdateLodLog=new Log();
            waitingUpdateLodLog.setId(waitingInsertLog.getId());
            waitingUpdateLodLog.setTitle("1111");
            waitingUpdateLodLog.setDataId("10000");
            waitingUpdateLodLog.setContent("test content test....");
            int updateStatus= logMapper.update(waitingUpdateLodLog);
    
            System.out.println("update result:"+logMapper.getById(waitingUpdateLodLog.getId()));
            
            // where:Pojo Parameter Map 三种传递参数的用法
            System.out.println("=========================================");
    
            String title = "test";
            ModuleType moduleType = ModuleType.Article_Category_Module;
            OperateType operateType = OperateType.Create;
    
            Log log = new Log();
            log.setTitle(title);
            log.setModuleType(moduleType);
            log.setOperateType(operateType);
            List<Log> logList = logMapper.getByPojo(log);
            for (Log item : logList) {
                System.out.println(item);
            }
            System.out.println("==========================================================");
    
            logList = logMapper.getByParameter(title, moduleType, operateType);
            for (Log item : logList) {
                System.out.println(item);
            }
            System.out.println("==========================================================");
    
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("title", title);
            parameterMap.put("moduleType", moduleType);
            parameterMap.put("operateType", operateType);
            logList = logMapper.getByMap(parameterMap);
            for (Log item : logList) {
                System.out.println(item);
            }
            
            sqlSession.commit();
            sqlSession.close();
        }
    }
    View Code

    备注:
    1)这里moduleType、operateType都是enum类型,在mybatis-config.xml中已经注册typeHandlers:

        <typeHandlers>
            <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.dx.test.model.enums.ModuleType"/>
            <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.dx.test.model.enums.OperateType"/>
        </typeHandlers>

    因此,这里完全不需要使用typeHandler、javaType属性

    {fieldName,typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler,javaType=com.dx.test.model.enums.OperateType}

    ,当然如果加上这两个属性也不会抛出异常。
    2)如果字段属性类型为enum时,不能判定该值是否不为空字符串或者不为字符串0,这两种用法都不正确,都会导致最终抛出异常:比如:

    <if test="moduleType!=null and moduleType!='' ">
      and `module_type`=#{moduleType}
    </if> 
    Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: 
    ### Error querying database.  Cause: java.lang.IllegalArgumentException: invalid comparison: com.dx.test.model.enums.ModuleType and java.lang.String
    ### Cause: java.lang.IllegalArgumentException: invalid comparison: com.dx.test.model.enums.ModuleType and java.lang.String
            at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
            at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
            at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
            at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:139)
            at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:76)
            at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
            at com.sun.proxy.$Proxy13.getByPojo(Unknown Source)
            at com.dx.test.MybatisTest.main(MybatisTest.java:71)

    <if test="moduleType!=null and moduleType!='0' ">
      and `module_type`=#{moduleType}
    </if>
    Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: 
    ### Error querying database.  Cause: java.lang.NumberFormatException: For input string: "Article_Category_Module"
    ### Cause: java.lang.NumberFormatException: For input string: "Article_Category_Module"
            at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
            at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
            at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
            at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:139)
            at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:76)
            at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
            at com.sun.proxy.$Proxy13.getByPojo(Unknown Source)
            at com.dx.test.MybatisTest.main(MybatisTest.java:71)

    3)上边例子中接收参数并未标注参数名称,如果加上参数别名标注:List<Log> getByPojo(@Param("log") Log log);,这时在<script>中的sql中访问相关属性要访问log对象下属性:

            @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
            @ResultMap("logResult")
            @Select(value={ 
                    "<script>",
                    "select * from `log` " ,
                    "<where>" ,
                    "     <if test="log.title!=null and log.title!=''">" ,
                    "          and `title` like CONCAT('%', #{log.title}, '%') " , 
                    "     </if>" ,
                    "     <if test="log.moduleType!=null ">" , 
                    "          and `module_type`=#{log.moduleType} " , 
                    "     </if>" , 
                    "     <if test="log.operateType!=null ">" , 
                    "          and `operate_type`=#{log.operateType} " , 
                    "     </if>" , 
                    "</where>",
                    "</script>"
                    })
            List<Log> getByPojo(@Param("log") Log log);

    否则会找不到相关属性,抛出异常:

    Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: 
    ### Error querying database.  Cause: org.apache.ibatis.binding.BindingException: Parameter 'title' not found. Available parameters are [log, param1]
    ### Cause: org.apache.ibatis.binding.BindingException: Parameter 'title' not found. Available parameters are [log, param1]
            at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
            at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
            at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
            at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:139)
            at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:76)
            at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
            at com.sun.proxy.$Proxy13.getByPojo(Unknown Source)
            at com.dx.test.MybatisTest.main(MybatisTest.java:71)

    通过普通多个参数传递

            @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
            @ResultMap("logResult")
            @Select(value={ 
                            "<script>",
                            "select * from `log` " ,
                            "<where>" ,
                            "     <if test="title!=null and title!=''">" ,
                            "          and `title` like CONCAT('%', #{title}, '%') " , 
                            "     </if>" ,
                            "     <if test="moduleType!=null ">" , 
                            "          and `module_type`=#{moduleType} " , 
                            "     </if>" , 
                            "     <if test="operateType!=null ">" , 
                            "          and `operate_type`=#{operateType} " , 
                            "     </if>" , 
                            "</where>",
                            "</script>"
                            })
            List<Log>  getByParameter(@Param("title") String title,@Param("moduleType") ModuleType moduleType,@Param("operateType") OperateType operateType);

    这种方法比较容易理解,但是缺点需要逐个定义相关参数。

    通过Map传递参数

            @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
            @ResultMap("logResult")
            @Select(value={ 
                            "<script>",
                            "select * from `log` " ,
                            "<where>" ,
                            "     <if test="title!=null and title!=''">" ,
                            "          and `title` like CONCAT('%', #{title}, '%') " , 
                            "     </if>" ,
                            "     <if test="moduleType!=null ">" , 
                            "          and `module_type`=#{moduleType} " , 
                            "     </if>" , 
                            "     <if test="operateType!=null ">" , 
                            "          and `operate_type`=#{operateType} " , 
                            "     </if>" , 
                            "</where>",
                            "</script>"
                            })
            List<Log> getByMap(Map<String, Object> map);

    备注:
    1)这种方案由于传递的也是对象,和传递POJO一样,如果不定义@Param在<script>内部直接方案相关属性即可;
    2)当在参数前定义了@Param时,比如:List<Log> getByMap(@Param("log") Map<String, Object> map);,此时访问属性时,必须加上map.前缀。

            @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
            @ResultMap("logResult")
            @Select(value={ 
                            "<script>",
                            "select * from `log` " ,
                            "<where>" ,
                            "     <if test="map.title!=null and map.title!=''">" ,
                            "          and `title` like CONCAT('%', #{map.title}, '%') " , 
                            "     </if>" ,
                            "     <if test="map.moduleType!=null ">" , 
                            "          and `module_type`=#{map.moduleType} " , 
                            "     </if>" , 
                            "     <if test="map.operateType!=null ">" , 
                            "          and `operate_type`=#{map.operateType} " , 
                            "     </if>" , 
                            "</where>",
                            "</script>"
                            })
            List<Log> getByMap(@Param("map") Map<String, Object> map);

    Trim替代Where、Set等

    针对上边的用法我们可以把getByMap(Map<String,Object> map)中Script中where使用trim来替代,例如:

        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @ResultMap("logResult")
        @Select(value={ 
                "<script>", 
                "select * from `log` " ,
                "<trim prefix="where" prefixOverrides="and |or |abc ">" ,
                "     <if test="title!=null and title!=''">" ,
                "          and `title` like CONCAT('%', #{title}, '%') " , 
                "     </if>" ,
                "     <if test="moduleType!=null ">" , 
                "          and `module_type`=#{moduleType} " , 
                "     </if>" , 
                "     <if test="operateType!=null ">" , 
                "          and `operate_type`=#{operateType} " , 
                "     </if>" , 
                "</trim>",
                "</script>"
                })
        List<Log> getByMap(Map<String, Object> map);

    1)prefixOverrides:前缀覆盖也就是说,where的后面紧跟着的是 andorabc,那么这些关键字都会被忽略
    2)要注意 | 后面不能有空格,例如: |a 和| a 后面这个a和|之间有空格,会导致忽略失

    Choose的用法:

        @Options(useCache = true, flushCache = Options.FlushCachePolicy.FALSE, timeout = 60000)
        @ResultMap("logResult")
        @Select({ 
            "<script>",
            "select * from `log` " ,
            "<where>" ,
            "    <choose> ",
            "        <when test="dataId!=null">",
            "            and data_id=#{dataId}",
            "        </when>",
            "        <when test="id!=null">",
            "            and id=#{id}",
            "        </when>",
            "        <otherwise>",
            "            and 1=1",
            "        </otherwise>",
            "    </choose>",
            "</where>" ,
            "</script>"})
        List<Log> getList(final Log log);

    注:choose相当于Java中的switch语句;当第一个when满足时,就只执行第一个when中的条件。当when中的条件都不满足时,就会执行默认的代码块,也就是otherwise中的语句。

    Set的用法

        @Options(useCache = true, flushCache = Options.FlushCachePolicy.TRUE)
        @Update({ 
            "<script>",
            "update `log` " ,
            "<set>" ,
            "    <if test="dataId!=null">",
            "        `data_id`=#{dataId},",
            "    </if>",
            "    <if test="title!=null">",
            "        `title`=#{title},",
            "    </if>",
            "    <if test="content!=null">",
            "        `content`=#{content} ",
            "    </if>",
            "</set>" ,
            " where id=#{id}",
            "</script>"})
        int update(final Log log);

    该set用法也可以使用trim来替代:

        @Options(useCache = true, flushCache = Options.FlushCachePolicy.TRUE)
        @Update({ 
            "<script>",
            "update `log` " ,
            "<trim prefix="SET" suffixOverrides=", |abc ">" ,
            "    <if test="dataId!=null">",
            "        `data_id`=#{dataId},",
            "    </if>",
            "    <if test="title!=null">",
            "        `title`=#{title},",
            "    </if>",
            "    <if test="content!=null">",
            "        `content`=#{content}, ",
            "    </if>",
            "</trim>" ,
            " where id=#{id}",
            "</script>"})
        int update(final Log log);

    使用<trim>定义<set>规则:
    1)suffixOverrides=", |abc",定义了无论是逗号","结尾还是"abc"结尾,都会被程序忽视,上面程序正常运行;
    2)文中的abc规则是我添加的,原本只有过滤逗号","。

  • 相关阅读:
    37.leetcode11_container_with_most_water
    36.leetcode8_string_to_integer
    34.leetcode15&5_time_limit_exceeded
    35.leetcode15_3Sum
    33.leetcode6_zigzag_conversion
    32.leetcode3_longest_substring_without_repeating_characters
    31.leetcode2_add_two_numbers
    29.leetcode172_factorial_trailing_zeroes
    30.leetcode171_excel_sheet_column_number
    [LeetCode] 43.Multiply Strings 字符串相乘
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/12026407.html
Copyright © 2020-2023  润新知