Mybatis---动态查询(choose,when,otherwise)

本文介绍MyBatis中choose元素的使用方法,通过示例详细解释了如何利用choose实现或逻辑,以及如何结合when和otherwise标签进行条件判断。

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。而使用if标签时,只要test中的表达式为 true,就会执行 if 标签中的条件。MyBatis 提供了 choose 元素。if标签是与(and)的关系,而 choose 是或(or)的关系。

choose标签是按顺序判断其内部when标签中的test条件出否成立,如果有一个成立,则 choose 结束。当 choose 中所有 when 的条件都不满则时,则执行 otherwise 中的sql。类似于Java 的 switch 语句,choose 为 switch,when 为 case,otherwise 则为 default。

例如下面例子,同样把所有可以限制的条件都写上,方面使用。choose会从上到下选择一个when标签的test为true的sql执行。安全考虑,我们使用where将choose包起来,放置关键字多于错误。

<!--  choose(判断参数) - 按顺序将实体类 User 第一个不为空的属性作为:where条件 -->  
<select id="selectControlTableColumnByTableColumnIdAndIsUpdateOrIsDelete"  parameterType="com.uama.mdm.model.mdata.MdControlTableColumn" resultMap="BaseResultMap">
        SELECT
        <include refid="Base_Column_list"></include>
        FROM md_control_table_column u
        <where>
            <choose>
                <when test="isUpdate !=null ">
                    AND u.is_update = #{isUpdate, jdbcType=INTEGER}
                </when>
                <when test="isDelete != null">
                    AND u.is_delete = #{isDelete, jdbcType=INTEGER}
                </when>
                <otherwise>
                </otherwise>
            </choose>
            <if test="tableColumnId != null">
               AND table_column_id = #{tableColumnId}
            </if>
        </where>
    </select>
<think>我们之前讨论的是mybatis-spring-boot-starter的保存操作,现在用户转向了“动态视图”的询问。注意,在MyBatis中,“动态视图”并不是一个标准术语。根据用户的问题,我们推测用户可能想了解MyBatis中的动态SQL功能,因为动态SQL允许根据条件动态构建SQL语句,类似于动态地“视图”生成。 但是,为了严谨,我们先明确:在MyBatis中,没有专门称为“动态视图”的特性。用户可能指的是: 1. 动态SQL:根据条件动态生成SQL语句。 2. MyBatis的关联查询(如association, collection)中的动态加载(例如延迟加载),这也可以视为一种动态视图的生成。 然而,用户引用的内容中并没有提到动态视图,因此我们主要依据MyBatis官方文档对动态SQL进行介绍,并适当结合动态加载(延迟加载)的内容。 根据引用[1]和[3],我们知道MyBatis-Spring-Boot-Starter会自动扫描@Mapper注解的接口,并创建实现类。在Mapper接口中,我们可以使用注解XML编写SQL,而动态SQL通常是在XML中实现的,但注解方式也可以通过@SelectProvider等实现。 所以,我们将从以下两个方面回答: 1. 动态SQL:使用XMLSQL构建器类动态生成SQL语句。 2. 延迟加载:在关联查询时,根据需要动态加载关联对象(可以看作是一种动态视图的生成)。 但注意:用户的问题中明确提到了“动态视图”,而MyBatis官方文档中并没有这个术语,因此我们按照最接近的动态SQL和延迟加载来解答。 步骤: 1. 介绍动态SQL(包括XML方式和注解方式) 2. 介绍延迟加载(动态加载关联对象) 注意:在回答中,我们尽量使用用户之前提到的引用内容,并补充新的引用(如果有的话)。 由于用户之前的引用[1][2][3]并没有直接提到动态SQL,因此我们主要依据MyBatis官方文档,但可以在回答中提及这些引用中相关的部分(例如Mapper的配置)。 我们还需要注意,用户使用的是MyBatis-Spring-Boot-Starter,因此要结合Spring Boot的配置。 下面开始组织回答: </think> ### MyBatis-Spring-Boot-Starter 动态视图使用详解 动态视图是 MyBatis 中强大的 SQL 构建功能,允许根据运行时条件动态生成 SQL 语句片段。在 MyBatis-Spring-Boot 项目中,主要通过以下方式实现: --- #### 一、核心实现方式 1. **XML 映射文件中的动态 SQL** ```xml <!-- 用户查询示例 --> <select id="findUsers" resultType="User"> SELECT * FROM users <where> <!-- 动态条件判断 --> <if test="name != null and name != ''"> AND name LIKE CONCAT('%', #{name}, '%') </if> <if test="minAge != null"> AND age >= #{minAge} </if> <!-- 动态排序 --> <choose> <when test="orderBy == 'create_time'"> ORDER BY create_time DESC </when> <otherwise> ORDER BY id </otherwise> </choose> </where> </select> ``` 2. **注解方式动态 SQL** ```java @SelectProvider(type = UserSqlBuilder.class, method = "buildQuery") List<User> findDynamicUsers(@Param("name") String name, @Param("minAge") Integer minAge); // SQL构建器类 class UserSqlBuilder { public String buildQuery(Map<String, Object> params) { return new SQL() {{ SELECT("*"); FROM("users"); if (params.get("name") != null) { WHERE("name LIKE CONCAT('%', #{name}, '%')"); } if (params.get("minAge") != null) { WHERE("age >= #{minAge}"); } }}.toString(); } } ``` --- #### 二、关键动态元素 1. **`<if>`**:条件判断 ```xml <if test="email != null"> AND email = #{email} </if> ``` 2. **`<choose>/<when>/<otherwise>`**:多分支选择 ```xml <choose> <when test="status == 1">AND status = 'ACTIVE'</when> <when test="status == 0">AND status = 'INACTIVE'</when> <otherwise>AND status IS NOT NULL</otherwise> </choose> ``` 3. **`<foreach>`**:集合遍历(IN 查询) ```xml WHERE id IN <foreach item="id" collection="ids" open="(" separator="," close=")"> #{id} </foreach> ``` 4. **`<bind>`**:创建变量(避免 SQL 注入) ```xml <bind name="pattern" value="'%' + name + '%'" /> WHERE username LIKE #{pattern} ``` --- #### 三、Spring Boot 集成配置 在 `application.yml` 中启用动态 SQL 支持: ```yaml mybatis: configuration: default-scripting-language: org.apache.ibatis.scripting.xmltags.XMLLanguageDriver aggressive-lazy-loading: false # 禁用延迟加载 ``` --- #### 四、最佳实践 1. **动态结果映射** ```xml <resultMap id="userMap" type="User"> <id property="id" column="id"/> <!-- 动态字段映射 --> <discriminator javaType="int" column="user_type"> <case value="1" resultType="AdminUser"/> <case value="2" resultType="NormalUser"/> </discriminator> </resultMap> ``` 2. **视图对象动态选择** ```java @Select("SELECT * FROM ${tableName} WHERE id = #{id}") <T> T selectDynamicTable(@Param("tableName") String table, @Param("id") Long id, Class<T> resultType); ``` 3. **安全注意事项** - 避免直接拼接 `${}` 表达式(有 SQL 注入风险) - 使用 `<bind>` 预处理语句处理用户输入 -动态表名/列名进行白名单校验 --- #### 五、性能优化建议 1. 使用二级缓存减少重复查询 ```xml <cache eviction="LRU" flushInterval="60000" size="512"/> ``` 2. 复杂动态 SQL 使用存储过程 ```java @Options(statementType = StatementType.CALLABLE) @Select("{call dynamic_user_query(#{name,mode=IN})}") List<User> callDynamicProcedure(String name); ``` > 动态视图通过条件分支和循环结构大幅提升 SQL 灵活性,适用于复杂业务场景下的查询构建[^1][^2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值