Mybatis动态SQL与模糊查询

本文介绍了Mybatis中如何进行动态SQL操作,特别是针对模糊查询和多条件查询的应用。通过创建表并定义查询条件类,展示了在不输入特定查询参数时避免错误的方法。在Mybatis映射文件中配置了条件判断,确保查询的灵活性和安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mybatis动态SQL与模糊查询

创建User

CREATE TABLE d_user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(10),
    age INT(3)
);
insert into d_user(name,age) values('Tom',12);
insert into d_user(name,age) values('Bob',13);
insert into d_user(name,age) values('Jack',18);

需要实现多条件查询用户(姓名模糊匹配, 年龄在指定的最小值到最大值之间)

定义查询条件类ConditionUser,如下:

package mybatis.bean;

public class ConditionUser {

    private String name;
    private int minAge;
    private int maxAge;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getMinAge() {
        return minAge;
    }
    public void setMinAge(int minAge) {
        this.minAge = minAge;
    }
    public int getMaxAge() {
        return maxAge;
    }
    public void setMaxAge(int maxAge) {
        this.maxAge = maxAge;
    }
    @Override
    public String toString() {
        return "ConditionUser [name=" + name + ", minAge=" + minAge + ", maxAge=" + maxAge + "]";
    }
    public ConditionUser(String name, int minAge, int maxAge) {
        super();
        this.name = name;
        this.minAge = minAge;
        this.maxAge = maxAge;
    }

    public ConditionUser() {
    }

}

userMapper.xml中使用如下的查询方式

<select id="getUser" parameterType="mybatis.bean.ConditionUser" resultType="mybatis.bean.User">
    select * from d_user where name like #{name} and age between #{minAge} and #{maxAge} 
</select>

查询过程如下:

    ConditionUser param = new ConditionUser("%o%", 13, 18);

    List<mybatis.bean.User> users = session.selectList("mybatis.test7.userMapper.getUser", param);
    for (mybatis.bean.User user : users) {
        System.out.println(user);
    }

会输出查询结果。

但这样做,还要一个问题,假设当前需要查询的name,用户没有输入,则会出错,如何解决呢?

userMapper.xml中的配置如下:

<select id="getUser" parameterType="mybatis.bean.ConditionUser" resultType="mybatis.bean.User">
    select * from d_user where 
    <if test='name!="%null%"'>name like #{name} and</if>
    age between #{minAge} and #{maxAge} 
</select>

查询测试如下:

    ConditionUser param = new ConditionUser("%null%", 13, 18);

    List<mybatis.bean.User> users = session.selectList("mybatis.test7.userMapper.getUser", param);
    for (mybatis.bean.User user : users) {
        System.out.println(user);
    }
<think>好的,我现在需要回答用户关于MyBatis中如何实现动态SQL模糊查询的问题。首先,我要回忆一下MyBatis动态SQL功能,特别是模糊查询的实现方式。用户提到了动态SQL和模糊查询,可能需要结合使用<if>、<choose>等标签,以及不同的模糊查询方法。 根据用户提供的引用内容,特别是引用[1]、[3]、[4],他们展示了使用<if>和<choose>标签结合concat函数来处理模糊查询。例如,在引用[1]中,使用了name like #{name},但需要注意条件判断中的写法。引用[4]则明确使用了concat('%',#{userName},'%')来拼接通配符,这样可以避免SQL注入问题,同时也更符合预编译语句的习惯。 接下来,我需要考虑用户需要的示例。用户希望看到动态SQL的模糊查询示例,可能需要包括不同的情况,比如条件判断和多个参数的组合。例如,根据不同的条件动态添加模糊查询的语句,或者使用choose标签来处理多选一的情况。 另外,需要注意MyBatis中模糊查询的正确写法。直接使用like #{name}可能在传参时需要参数本身包含通配符,比如在Java代码中传入"%张三%",但这种方式不太灵活。更推荐在SQL中使用concat函数来拼接通配符,这样参数只需要传具体的值,如"张三",而SQL语句变成like concat('%', #{name}, '%'),这样更安全和方便。 然后,动态SQL部分,可能需要使用<where>标签来自动处理多余的AND或OR,避免语法错误。例如,在引用[4]中,使用了<where>标签包裹条件,这样即使第一个条件不成立,MyBatis也会自动去掉开头的AND。 此外,用户提供的引用[3]中提到了<choose>标签,类似于switch语句,可以根据不同的条件选择不同的分支。这在模糊查询中可能用于多条件选择,比如根据名称或邮箱进行模糊查询,或者根据其他字段进行查询。 现在需要将这些内容整合成一个清晰的示例。可能需要分步骤说明,比如使用<if>标签实现条件判断,结合concat进行模糊查询,或者使用<choose>进行多条件选择,同时展示如何防止SQL注入,并确保动态SQL的正确性。 最后,生成相关问题需要考虑用户可能进一步想了解的内容,比如动态SQL的其他标签、模糊查询的性能优化、不同数据库的差异处理等。</think>在MyBatis中实现动态SQL的模糊查询,通常需结合`<if>`、`<choose>`等动态标签SQL语句拼接函数(如`CONCAT`)。以下是具体实现方式及示例: --- ### 一、基础动态模糊查询示例 #### 1. 使用`<if>`标签`CONCAT`函数 ```xml <select id="searchUsers" resultType="User"> SELECT * FROM d_user <where> <if test="name != null and name != ''"> name LIKE CONCAT('%', #{name}, '%') <!--动态拼接通配符--> </if> <if test="email != null"> AND email = #{email} </if> </where> </select> ``` - **说明**: - `<where>`标签自动处理多余的`AND`或`OR`,避免语法错误[^4]。 - `CONCAT('%', #{name}, '%')`保证参数安全且无需手动添加`%`。 --- #### 2. 多条件选择`<choose>` ```xml <select id="findByCondition" resultType="User"> SELECT * FROM user <where> <choose> <when test="name != null"> name LIKE CONCAT('%', #{name}, '%') <!--优先按名称模糊查询--> </when> <when test="phone != null"> phone LIKE CONCAT('%', #{phone}, '%') <!--次优先按电话查询--> </when> <otherwise> status = 1 <!--默认查询有效用户--> </otherwise> </choose> </where> </select> ``` - **说明**:`<choose>`标签类似`switch-case`,仅执行第一个满足条件的分支[^3]。 --- ### 二、参数直接包含通配符(不推荐) 若需手动控制通配符位置,可直接传参`%value%`,但需注意SQL注入风险: ```xml <if test="keyword != null"> title LIKE #{keyword} <!--参数示例:"%Java%"--> </if> ``` --- ### 三、动态组合多字段模糊查询 ```xml <select id="multiFieldSearch" resultType="User"> SELECT * FROM product <where> <if test="keyword != null"> (name LIKE CONCAT('%', #{keyword}, '%') OR description LIKE CONCAT('%', #{keyword}, '%')) </if> <if test="category != null"> AND category_id = #{category} </if> </where> </select> ``` --- ### 四、注意事项 1. **通配符位置**:`CONCAT`灵活性更高,如`CONCAT(#{name}, '%')`实现前缀匹配。 2. **性能优化**:大量模糊查询时考虑索引优化或全文检索。 3. **防注入**:避免直接将用户输入拼接为`LIKE '%${value}%'`,应使用`#{}`占位符[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值