当前位置:   article > 正文

MyBatis(六)动态SQL_动态 sql 是 mybatis 的一个强大的特性。有以下几个特点: 根据不同的条件需要执行

动态 sql 是 mybatis 的一个强大的特性。有以下几个特点: 根据不同的条件需要执行

动态SQL

动态 SQL 是 MyBatis 的一个强大的特性。有以下几个特点:

  1. 根据不同的条件需要执行不同的 SQL 命令,称为动态 SQL
  2. MyBatis 通过 OGNL 表达式来进行动态SQL的使用。
  3. MyBatis 中动态 SQL 在 mapper.xml 中添加逻辑判断等。

常用标签

元素作用
if实现简单的条件选择,判断语句
choose(when,otherwise)相当于 Java 中的 switch 语句,通常与 when 和 otherwise 搭配使用
where简化 SQL 语句中 where 的条件判断
set解决动态更新语句
trim可以灵活去除多余的关键字
foreach迭代一个集合,通常用于 in 条件
bind创建一个变量,并绑定到上下文

1、 if 标签

1.1 在 were 条件中使用 if 标签(查询)

if 标签是我们最常使用的。必须结合 test 属性联合使用。

  1. 这个 SQL 中,使用了where 1=1,这是多条件拼接的小技巧,后面的条件查询就可以都用 and 了。
  2. if 标签的 test 属性值是一个符合 OGNL 的表达式,表达式可以是 true 或 false。如果表达式返回的是数值,则 0 为 false,非 0 为 true。
1.1.1 mapper

UserMapper.java

/**
 * 通过姓名进行模糊查询
 * @param user
 * @return
 */
List<User> selectUserByName(User user);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

UserMapper.xml

如果 name 为 null,则查询全部,否则模糊查询

<select id="selectUserByName" parameterType="User" resultType="User">
    select * from user where 1=1
    <if test="name != null">
        and name like concat('%', #{name},'%')
    </if>
</select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
1.1.2 测试
@org.junit.Test
public void selectUserByNameTest(){
    SqlSession session = factory.openSession();
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User user = new User();
    // 查询所有
    List<User> list = userMapper.selectUserByName(user);
    System.out.println(list);
    // 模糊查询
    user.setName("yu1");
    List<User> userList = userMapper.selectUserByName(user);
    System.out.println(userList);
    session.commit();
    session.close();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
1.1.3 测试结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mSQqShlE-1602291919154)(…/…/…/…/noteImage/image-20201009150011561.png)]

1.2 insert 动态插入中使用 if 标签

在我们插入数据库中的记录中,不是每一个字段都有值的,这个时候可以通过 if 标签来判断字段是否有值。

1.2.1 mapper

UserMapper.java

/**
 * 非空字段才进行插入
 * @param user
 * @return
 */
public int insertUser(User user);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

UserMapper.xml

<insert id="insertUser" parameterType="User">
    insert into user
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="name != null">
            name,
        </if>
        <if test="password != null">
            password,
        </if>
        <if test="phone != null">
            phone,
        </if>
        <if test="sex != null">
            sex,
        </if>
        <if test="birthday != null">
            birthday,
        </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
        <if test="name != null">
            #{name},
        </if>
        <if test="password != null">
            #{password},
        </if>
        <if test="phone != null">
            #{phone},
        </if>
        <if test="sex != null">
            #{sex},
        </if>
        <if test="birthday != null">
            #{birthday},
        </if>
    </trim>
</insert>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
1.2.2 测试
@org.junit.Test
public void insertUserTest(){
    SqlSession session = factory.openSession();
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User user = new User();
    user.setName("xiaoyu");
    user.setPassword("xiaoyu");
    user.setBirthday(new Date());
    user.setPhone("15870934313");
    user.setSex("男");
    System.out.println(userMapper.insertUser(user));
    session.commit();
    session.close();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
1.2.3 运行结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XjHV6dI3-1602291919158)(…/…/…/…/noteImage/image-20201009143802695.png)]

2、where 标签

  1. 当编写where标签时,如果内容中第一个是and就会去掉第一个and,
  2. 如果where标签中有内容会生成where关键字,如果没有内容不会生成where关键字
  3. 比直接使用if少写了where 1=1
2.1 mapper
List<User> selectUserByNameTag(User user);
  • 1
<select id="selectUserByNameTag" parameterType="User" resultType="User">
    select * from user
    <where>
        <if test="name != null">
            and name like concat('%', #{name},'%')
        </if>
    </where>
</select>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2.2 测试
@org.junit.Test
public void selectUserByNameTest2(){
    SqlSession session = factory.openSession();
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User user = new User();
    // 查询所有
    List<User> list = userMapper.selectUserByNameTag(user);
    System.out.println(list);
    // 模糊查询
    user.setName("yu1");
    List<User> userList = userMapper.selectUserByNameTag(user);
    System.out.println(userList);
    session.commit();
    session.close();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
2.3 测试结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G6IOBSJw-1602291919161)(…/…/…/…/noteImage/image-20201009151650994.png)]

3、choose、when、otherwise标签

  1. 只要有一个成立,其他都不成立

  2. 代码示例

    <select id="selectByNameAndPassword" resultType="User">
    	select * from user
    	<where>
    		<choose>
    			<when test="name != null">
    				and name = #{name}
    			</when>
    			<when test="password != null">
    				and password = #{password}
    			</when>
    		</choose>
    	</where>	
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

4、set标签

  1. 作用,去掉最后一个逗号

  2. 作用:如果里面有内容生成set关键字,没有就不生成。

当更新时传入空值时,可以将空值不更新

4.1 mapper
/**
 * 更新用户
 * @param user
 * @return
 */
int updateUser(User user);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
<update id="updateUser" parameterType="User">
    update user
    <set>
        <if test="name != null">
            name = #{name},
        </if>
        <if test="password != null">
            password = #{password},
        </if>
        <if test="phone != null">
            phone = #{phone},
        </if>
        <if test="sex != null">
            sex = #{sex},
        </if>
        <if test="birthday != null">
            birthday = #{birthday},
        </if>
    </set>
    where id = #{id}
</update>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
4.2 测试
@org.junit.Test
public void updateUserTest(){
    SqlSession session = factory.openSession();
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User user = new User();
    user.setId(2);
    user.setName("xiaoyu7");
    user.setPassword("xiaoyu7");
    user.setBirthday(new Date());
    user.setPhone("15870934313");
    user.setSex("男");
    System.out.println(userMapper.updateUser(user));
    session.commit();
    session.close();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
4.3 测试结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FJSePBjc-1602291919165)(…/…/…/…/noteImage/image-20201009150919570.png)]

5、trim标签

前面 1.1 里面使用了 trim,这里介绍一下用法。

5.1 trim 用来表示 where
<trim prefix="where" prefixOverrides="AND | OR"></trim>
  • 1

表示当 trim 里面有内容时,添加 where ,且第一个为 AND 或 OR 时,会将其去掉,而如果没有内容,则不添加 where。

5.2 trim 用来表示 set
<trim prefix="set" suffixOverrides=","></trim>
  • 1

表示当 trim 里面有内容时,添加 set ,且最后的内容为 , 时,会将其去掉,而如果没有内容,则不添加 set。

5.3 trim 的属性
  1. prefix:在前面添加内容

  2. prefixOverrides :去掉前面的内容

  3. suffix :在后面添加内容

  4. suffixOverrides :去掉后面内容

  5. 执行顺序是去掉内容后添加内容

6、bind标签

  1. 作用:通过 OGNL 表达式去定义一个上下文的变量

  2. 场景:

    1. 模糊查询
    2. 在原内容前或后添加内容
  3. 示例

    <select id="selectByLog" resultType="User" parameterType="User">
    	<bind name="name" value="'%' + name + '%'"/>
    	select * from user where name like #{name}
    </select>
    
    • 1
    • 2
    • 3
    • 4

7、foreach标签

  1. 循环参数内容,还具备在内容的前后添加内容,还具备添加分隔符的功能

  2. 适用场景:in查询。批量新增中(mybatis中foreach效率比较低)

    1. 如果希望批量新增,SQL命令
    2. openSession()必须指定
      1. 底层是JDBC的PreparedStatement.addBatch();
  3. 示例

    1. collection="" :要遍历的集合
    2. item="" :迭代变量,#{迭代变量名} 获取内容
    3. open="" :循环后左侧添加的内容
    4. close="" :循环后右侧添加的内容
    5. separator="" :循环分隔符
    6. index:索引的属性名。当迭代对象为 Map 时,该值为 Map 中的 Key。
    <select id="selectIn" parameterType="list" resultType="User">
    	select * from user where name in
    	<foreach collection="list" item="abc" open="(" close=")" separator=",">
    		#{abc}
    	</foreach>
    </select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 某些SQL片段如果希望复用,可以使用定义这个片段

    2. 在、、、中使用引用

      <select id="select">
      	select <include refid="mysql"></include>
      		from user
      </select>
      <sql id="mysql">
      	id,name,passowrd,sex,phone,birthday
      </sql>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/110130
推荐阅读
相关标签
  

闽ICP备14008679号