[华为云在线课程][MyBatis入门][三][动态SQL][学习笔记]

举报
John2021 发表于 2022/08/01 06:42:51 2022/08/01
【摘要】 动态SQL是MyBatis中非常强大的一个功能。例如一些常见的查询场景如查询条件不确定、批量插入等等。我们可以通过使用MyBatis提供的动态SQL来解决问题。 1.ifif是一个判断节点,如果满足条件节点中的SQL就会生效。比如分页查询,要传递页码和查询的记录数,如果这两个参数都为null,那么就要查询所有记录。首先定义接口:public interface UserMapper { ...

动态SQL是MyBatis中非常强大的一个功能。例如一些常见的查询场景如查询条件不确定、批量插入等等。我们可以通过使用MyBatis提供的动态SQL来解决问题。

1.if

if是一个判断节点,如果满足条件节点中的SQL就会生效。比如分页查询,要传递页码和查询的记录数,如果这两个参数都为null,那么就要查询所有记录。
首先定义接口:

public interface UserMapper {
    List<User> getUserByPage(@Param("start") Integer start,@Param("count") Integer count);
}

在xml中定义SQL

<!--分页查询-->
<select id="getUserByPage" resultType="org.example.mybatis01.model.User">
    select * from user
    <if test="start!=null and count!=null">
        limit #{start},#{count}
    </if>
</select>

在if节点中,test是指判断条件,如果结果为true,则if节点中的SQL生效。也就是说,如果分页的两个参数都为null,则查询所有数据。

@Test
public void getUserByPage() {
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userList = userMapper.getUserByPage(null, null);
    System.out.println(userList);
    System.out.println("###############################");
    List<User> userByPage = userMapper.getUserByPage(0, 1);
    System.out.println(userByPage);
}

2.choose

有时我们不想使用所有的条件,而是想从多个条件中使用一个。这时可以使用choose,它类似Java中的switch语句。
定义一个接口方法:

List<User> getUserByNameOrAddress(User user);

在XML中定义SQL

<resultMap id="UserResultMap" type="org.example.mybatis01.model.User">
    <constructor>
        <idArg column="id" name="id"/>
        <arg column="username" name="username"/>
        <arg column="address" name="address"/>
    </constructor>
</resultMap>
<select id="getUserByNameOrAddress" resultMap="UserResultMap" parameterType="org.example.mybatis01.model.User">
    select * from user
    where
    <choose>
        <when test="username!=null and username!=''">
            username=#{username}
        </when>
        <when test="address!=null and address!=''">
            address=#{address}
        </when>
    </choose>
</select>
@Test
public void getUserByNameOrAddress() {
    User user = new User();
    user.setAddress("testAddress01");
    user.setUsername("test01");
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userByNameOrAddress = userMapper.getUserByNameOrAddress(user);
    System.out.println(userByNameOrAddress);
}

输出结果:

<==      Total: 2
[User{id=7, username='test01', address='testAddress01'}, User{id=8, username='test01', address=''}]

3.where

where用来处理查询参数。以下有一个查询函数:

List<User> getUserByUsernameAndId(@Param("id") Integer id, @Param("name") String name);

这个查询的每个参数都是可选的,如果id为null,则根据name查询,如果name为null则根据id查询,两个都为null则查询所有。

<!--where查询-->
<select id="getUserByUsernameAndId" resultType="org.example.mybatis01.model.User">
    select * from user
    <where>
        <if test="id!=null">
            and id>#{id}
        </if>
        <if test="name!=null">
            and username like concat('%',#{name},'%')
        </if>
    </where>
</select>

用where节点将所有的查询条件包起来,如果有满足的条件,where节点自动加上,如果没有,where节点就不存在,在有满足条件情况下,where还会自动处理and关键字。

@Test
public void getUserByUsernameAndId() {
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> usernameAndId = userMapper.getUserByUsernameAndId(2, "cc");
    System.out.println(usernameAndId);//[User{id=3, username='cc', address='guangzhou'}]
    List<User> usernameAndId1 = userMapper.getUserByUsernameAndId(null, "bb");
    System.out.println(usernameAndId1);//[User{id=2, username='bb', address='shanghai'}]
    List<User> usernameAndId2 = userMapper.getUserByUsernameAndId(2, null);
    System.out.println(usernameAndId2);//[User{id=3, username='cc', address='guangzhou'}, User{id=4, username='dd', address='shenzhen'}]
    List<User> usernameAndId3 = userMapper.getUserByUsernameAndId(null, null);
    System.out.println(usernameAndId3);//[User{id=1, username='aaaa', address='beijing'}, User{id=2, username='bb', address='shanghai'}, User{id=3, username='cc', address='guangzhou'}, User{id=4, username='dd', address='shenzhen'}]
}

4.set

set关键字一般用在更新。大部分情况下,更新的字段可能不确定,如果对象中粗壮乃该字段的值,就更新该字段,不存在就不进行更新。例如以下代码:

Integer updateUser(User user);

现在要根据用户id来更新用户的其他属性,所以user对象中一定存在id,其他属性则不确定,有就进行更新,没有就不更新。

<update id="updateUser" parameterType="org.example.mybatis01.model.User">
    update user
    <set>
        <if test="username!=null">
            username=#{username},
        </if>
        <if test="address!=null">
            address=#{address},
        </if>
        <if test="favorites!=null">
            favorites=#{favorites},
        </if>
    </set>
    where id=#{id};
</update>
@Test
public void updateUser() {
    User user = new User();
    user.setId(1);
    user.setUsername("aaaa");
    int update = sqlSession.update("org.example.mybatis01.mapper.updateUser", user);
    System.out.println(update);  // 1
    sqlSession.commit();
}

5.trim

如果where的功能与期望的不一样,可以通过自定义trim元素来定制where元素的功能。

<select id="getUserByNameOrAddress2" resultMap="UserResultMap" parameterType="org.example.mybatis01.model.User">
    select * from user
    <trim prefix="where" prefixOverrides="and">
        <if test="username!=null and username!=''">
            and username=#{username}
        </if>
        <if test="address!=null and address!=''">
            and address=#{address}
        </if>
    </trim>
</select>
List<User> getUserByNameOrAddress2(User user);
@Test
public void getUserByNameOrAddress2() {
    User user = new User();
    user.setUsername("test01");
    user.setAddress("testAddress01");
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> userByNameOrAddress2 = userMapper.getUserByNameOrAddress2(user);
    System.out.println(userByNameOrAddress2);
}

prefixOverride属性会忽略通过管道符分割的文本序列。上述例子会移除所有prefixOverrides属性中指定的内容,并且插入 prefix 属性中指定的内容。

6.foreach

foreach用来处理数组/集合参数。例如,我们有一个批量查询的需求:

List<User> getUserByIds(@Param("ids") Integer[] ids);

编写对应XML

<select id="getUserByIds" resultType="org.example.mybatis01.model.User">
    select * from user where id in
    <foreach collection="ids" open="(" close=")" item="id" separator=",">
        #{id}
    </foreach>
</select>

在mapper中,通过foreach节点来遍历数组,collection表示数组变量,open表示循环结束后,左边的符号,close表示循环结束后,右边的符号,item表示循环时候的单个变量,separator表示循环的元素之间的分隔符。在默认情况下,无论数组/集合参数名字是什么,在xml中访问时候,都是array,开发者可以通过@Param注解给参数重新指定名字。
以下是一个批量插入的例子:

Integer batchInsertUser(@Param("users") List<User> users);
<insert id="batchInsertUser">
    insert into user(username,address) values
    <foreach collection="users" separator="," item="user">
        (#{user.username},#{user.address})
    </foreach>
</insert>
@Test
public void batchInsertUser() {
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    ArrayList<User> users = new ArrayList<>();
    User user = new User();
    user.setUsername("ee");
    user.setAddress("moon");
    users.add(user);
    User user1 = new User();
    user1.setUsername("ff");
    user1.setAddress("mars");
    users.add(user1);
    mapper.batchInsertUser(users);
    sqlSession.commit();
}

7.bind

bind元素运行在表达式之外创建一个变量,并将其绑定到当前的上下文。

<select id="getUsername" resultMap="UserResultMap">
    <bind name="nameLike" value="'%'+username+'%'"/>
    select * from user where username like #{nameLike};
</select>
List<User> getUsername(User user);
@Test
public void getUsername() {
    User user = new User();
    user.setUsername("t");
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    List<User> username = userMapper.getUsername(user);
    System.out.println(username);
}

输出结果:

<==      Total: 2
[User{id=7, username='test01', address='testAddress01'}, User{id=8, username='test01', address=''}]

8.MyBatis多数据库支持

首先在mybatis-config.xml里面配置多数据库支持

<databaseIdProvider type="DB_VENDOR">
    <property name="MySQL" value="mysql"/>
    <property name="Oracle" value="oracle"/>
</databaseIdProvider>
<select id="getUsername" resultMap="UserResultMap" databaseId="mysql">
    <bind name="nameLike" value="'%'+username+'%'"/>
    select * from user where username like #{nameLike};
</select>
<select id="getUsername" resultMap="UserResultMap" databaseId="oracle">
    <bind name="nameLike" value="'%'+username+'%'"/>
    select * from user where username like #{nameLike};
</select>
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。