mybatis的动态sql详解

1. 什么是MyBatis动态SQL?

MyBatis动态SQL是指在MyBatis的Mapper接口中,可以根据不同条件拼接不同的SQL语句,实现条件匹配的灵活查询,大大增强了MyBatis的灵活性和可扩展性。

1.1 为什么要用动态SQL?

使用动态SQL可以实现SQL语句的灵活组合,不需要额外编写不同的SQL示例,大大提高了代码的重用率和可维护性。

1.2 动态SQL的使用方式

MyBatis中使用动态SQL语句,可以通过<if>、<choose>、<when>、<otherwise>、<where>、<set>标签等进行拼接。

<if>标签:表示某个条件成立时,将此标签内的SQL语句进行拼接;

<choose>标签:与if标签类似,但是可以包含多个when和一个otherwise,用于多条件判断并拼接不同的SQL语句;

<where>标签:用于在拼接SQL时,自动忽略无效的SQL语句(例如AND、OR关键字);

<set>标签:用于拼接UPDATE表操作中的字段赋值部分的SQL语句。

1.3 动态SQL的实例

例如,我们有一个User表,有以下字段:

CREATE TABLE User (

id INT NOT NULL AUTO_INCREMENT,

name VARCHAR(20) NOT NULL default '',

age INT NOT NULL default 0,

PRIMARY KEY (id)

);

现在我们需要通过用户姓名和年龄进行条件查询,但是姓名和年龄并不一定都有,有可能只有姓名或只有年龄。

此时,我们可以使用如下的动态SQL:

<select id="getUserByNameAndAge" resultMap="userMap">

select id,name,age from User

<if test="name != null">

where name = #{name}

</if>

<if test="name != null and age != null">

and

</if>

<if test="age != null">

age = #{age}

</if>

</select>

以上代码中,我们使用了<if>标签,根据不同条件来拼接不同的SQL语句。这样,我们就可以根据姓名和年龄的不同组合进行条件查询了。

2. MyBatis动态SQL的其他用法

2.1 foreach标签

MyBatis的foreach标签可以用于遍历一个集合,并将集合中的元素拼接成SQL语句中的IN条件。

例如,我们有一个ids集合:

List<Integer> ids = new ArrayList<>();

ids.add(1);

ids.add(2);

ids.add(3);

我们可以使用foreach标签将这个集合拼接成IN条件:

<select id="getUsersByIds" resultMap="userMap">

select id,name,age from User

where id in

<foreach collection="ids" item="id" separator="," open="(" close=")">

#{id}

</foreach>

</select>

以上代码中,我们使用了<foreach>标签,将集合中的元素拼接成SQL语句中的IN条件。其中,collection属性用于指定遍历的集合名称,item属性表示每次遍历的元素,separator属性表示元素间的分隔符,open属性表示IN条件开始的字符,close属性表示IN条件结束的字符。

2.2 bind标签

MyBatis的bind标签可以用于定义一个变量,并将其在SQL语句中多次引用。

例如,我们需要查询姓名为Tom的用户,并且需要按照年龄排序,但是年龄比35小的用户需要排在年龄比35大的用户前面。

此时,我们可以使用bind标签定义一个变量:

<select id="getUsersByName" resultMap="userMap">

<bind name="ageThreshold" value="35" />

select id,name,age from User

where name = #{name}

order by

<if test="age != null">

<if test="age < ageThreshold">

age asc, id asc

</if>

<if test="age >= ageThreshold">

age desc, id asc

</if>

</if>

<if test="age == null">

id asc

</if>

</select>

以上代码中,我们使用了bind标签,定义了一个名为ageThreshold的变量,值为35。我们在SQL语句中引用了这个变量,可以避免多次写重复的35的值。同时,我们也使用了<if>标签,根据不同条件拼接不同的SQL语句。

2.3 trim标签

MyBatis的trim标签可以用于自动忽略SQL语句中的关键字,避免生成无效的SQL语句。

例如,我们需要按照年龄范围进行查询:

<select id="getUsersByAgeRange" resultMap="userMap">

select id,name,age from User

<trim prefix="where" prefixOverrides="and|or">

<if test="minAge != null">

and age >= #{minAge}

</if>

<if test="maxAge != null">

and age <= #{maxAge}

</if>

</trim>

</select>

以上代码中,我们使用了<trim>标签,prefix属性表示要拼接的关键字,prefixOverrides属性表示要忽略的关键字。其中,prefix、prefixOverrides属性都可以省略不写。同时,我们也使用了<if>标签,根据不同条件拼接不同的SQL语句。

3. 总结

MyBatis的动态SQL功能极为强大,可以实现在同一个Mapper接口中,根据不同条件拼接不同的SQL语句,非常灵活方便。其中,<if>、<choose>、<when>、<otherwise>、<where>、<set>、<foreach>、<bind>、<trim>等标签都可以用来实现动态SQL。

在使用动态SQL时,需要根据具体情况选择合适的标签,并注意代码的可读性和可维护性。

数据库标签