Mybatis---动态sql

目录

一、动态sql介绍

二、if

(1)持久层接口方法

(2)映射文件

(3)测试方法 

三、where

四、set

(1)持久层接口方法

(2)映射文件

(3)测试方法

五、choose和otherwise

六、foreach

(1)遍历数组

      (1)持久层接口方法

       (2)映射文件

        (3)测试方法

(2)遍历Collection

       (1)持久层接口方法

        (2)映射文件 

        (3)测试方法

(3)遍历Map

      (1)持久层接口方法

      (2)映射文件

      (3)测试方法


一、动态sql介绍

一个查询的方法的sql语句不一定是固定的,比如电商网站的查询商品,用户使用不同条件查询,sql语句就会添加不同的查询条件。此时就需要用到动态sql了。

二、if

<if>标签内的sql片段在满足条件后才会添加,用法为<if test="">如下:根据不同条件查询用户

(1)持久层接口方法



//动态sql
public interface UserMapper1 {
    List<User> findByif(User user);
}

(2)映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gq.mapper.UserMapper1">
    <select id="findByif" parameterType="com.gq.pojo.User" resultType="com.gq.pojo.User">
        select *from user where 1=1
        <if test="username!=null and username.length()!=0">
            and username like #{username}
        </if>
        <if test="sex!=null and sex.length()!=0">
            and sex = #{sex}
        </if>
        <if test="address!=null and address.length()!=0">
            and address = #{address}
        </if>
    </select>


</mapper>
        <!---->

这里为什么要有where 1=1呢,重点是后面一直用and拼接。

对于该映射文件我的理解如下:

从user表中查找有符号if标签中的条件的,有一个就查一个都可以。

(3)测试方法 

  @Test
    public void sqlifTest() throws Exception{
        InputStream is=Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(is);
        SqlSession session=sqlSessionFactory.openSession();
        UserMapper1 userMapper1=session.getMapper(UserMapper1.class);
        User user=new User();
        user.setUsername("%尚学堂%");

       List<User> userList=userMapper1.findByif(user);
       userList.forEach(System.out::println);
        session.commit();
        session.close();
        is.close();
    }

三、where

<where>可以代替sql中的where 1=1 和第一个and,更符合程序员的开发,所以我们可以将(2)中的映射文件修改成如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gq.mapper.UserMapper1">
    <select id="findByif" parameterType="com.gq.pojo.User" resultType="com.gq.pojo.User">
        select *from user
        <where>
            <if test="username!=null and username.length()!=0">
                username like #{username}
            </if>
            <if test="sex!=null and sex.length()!=0">
                and sex =#{sex}
            </if>
            <if test="address!=null and address.length()!=0">
                and address=#{address}
            </if>
        </where>
    </select>


</mapper>
        <!---->

四、set

(1)持久层接口方法

public interface UserMapper1 {

    //更新用户
    void updatesql(User user);
}

(2)映射文件

    <update id="updatesql" parameterType="com.gq.pojo.User">
        update user
<set>
  <if test="username!=null and username.length()!=0">
      username=#{username},
  </if>
  <if test="address!=null and address.length()!=0">
      address=#{address},
  </if>
    <if test="sex!=null and sex.length()!=0">
        sex=#{sex}
    </if>
<where>
    id=#{id}
</where>
</set>
    </update>

(3)测试方法

 @Test
    public void sqlUpdateTest() throws Exception{
        InputStream is=Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(is);
        SqlSession session=sqlSessionFactory.openSession();
        UserMapper1 userMapper1=session.getMapper(UserMapper1.class);
        User user=new User(8,"玉玉","男","安徽");
        userMapper1.updatesql(user);
        session.commit();
        session.close();
        is.close();
    }

五、choose和otherwise

 <select id="findchoose" parameterType="com.gq.pojo.User" resultType="com.gq.pojo.User">
        select *from user
        <where>
            <choose>
                <when test="username.length() &lt; 5">
                    username like #{username}
                </when>
                <when test="username.length() &lt; 10">
                    username = #{username}
                </when>
                <otherwise>
                    id=1
                </otherwise>
            </choose>
        </where>
    </select>

其实这些标签就相当于swithch...case,上面代码的含义是:

用户名长度<5时使用模糊查询,用户名大于等于5并且小于10时使用精确查询,否则就查找id等于1的用户

六、foreach

foreach类似于Java中的for循环,可以遍历数组或者集合,<foreach>有如下属性:

(1)collection:遍历的对象类型

(2)open:开始的sql语句

(3)close:结束的sql语句

(4)separator:遍历每项间的分隔符

(5)item:表示本次遍历获取遍历的元素,遍历List,Set,数组时表示每项元素,遍历map时表示键值对的值。

(6)index:遍历List,数组时表示遍历的索引,遍历map时表示键值对的键

(1)遍历数组

      (1)持久层接口方法

//动态sql
public interface UserMapper1 {
   
    //批量删除用户
    void deleteArray(int[] ids);
}

       (2)映射文件

<delete id="deleteArray" parameterType="int">
        delete from user
        <where>
            <foreach collection="array" open="id in (" close=")" separator="," item="id">
                #{id}
            </foreach>
        </where>
    </delete>

我的理解如下:

正常的sql语句是 delte from user where id in(1,2,3)。

而我们想要批量删除,那我们需要遍历他的id,也就是说id是被遍历的。

collection遍历的对象类型是数组,则为array

open表示开始的sql语句,我们是从where后面开始的,也就是id in (。为什么到这里呢?因为在后面就是具体被遍历的值了,那就是后面的item了,在后面就是)结尾,但很明显)是close。

seperator遍历每项间的分隔符,在id in (1,2,3)中,1,2,3,他们是以逗号分隔的,所以值就是“,”。

item表示遍历获取的元素。

在foreach中将自己遍历到的值补充好,使其成为完整的sql语句。

        (3)测试方法

 

@Test
    public void sqlfordeleteTest() throws Exception{
        InputStream is=Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(is);
        SqlSession session=sqlSessionFactory.openSession();
        UserMapper1 userMapper1=session.getMapper(UserMapper1.class);
        int[] arr={7,8,9};
        userMapper1.deleteArray(arr);
        session.commit();
        session.close();
        is.close();
    }

(2)遍历Collection

因为<foreach>遍历List和Set的方法是一样的,所以我就列举遍历List的用法了。

       (1)持久层接口方法

//动态sql
public interface UserMapper1 {

    //批量添加用户
    void addListUser(List<User> users);
}

        (2)映射文件 

 <insert id="addListUser" parameterType="com.gq.pojo.User">
        insert into user(username,sex,address) values
        <foreach collection="list" separator="," item="users">
            (#{users.username},#{users.sex},#{users.address})
        </foreach>
    </insert>

这里我的理解是这样的:

原来的正常sql语句应该是insert into user(username,sex,address) values("李四","男","天津"),("王五","女","重庆"),("赵六","男","沈阳");

collection表示遍历对象类型,这里是list

这里我们循环的是每次插入的那个值,所以应该是从values后面开始循环,并且每次他都自己要有(),中间以逗号分隔,很明显不要使用open和close

        (3)测试方法

(3)遍历Map

这里Map中的键值对存储的是查找对象的具体属性,键表示的属性名,值表示的是属性值。

比如说 select *from user where username="张三";

这里的键表示的是如username,sex,address等等

值就是他们的具体值了。

      (1)持久层接口方法

//动态sql
public interface UserMapper1 {
    List<User> selectMap(@Param("quMap")Map<String,Object> maps);
}

这里用@Param给参数取名字主要是为了后面映射文件中的<Map>遍历中的collection,不同于List和set他们,遍历Map他的collection值并不是map,而是你要给参数取名字,并且它的collection值就等于他

      (2)映射文件

  

    <select id="selectMap" parameterType="map" resultType="com.gq.pojo.User">
        select *from user
<where>
    <foreach collection="quMap" separator="and" index="key" item="val">
        ${key}=#{val}
    </foreach>
</where>
    </select>

      (3)测试方法

  @Test
    public void sqlforMapTest() throws Exception{
        InputStream is=Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(is);
        SqlSession session=sqlSessionFactory.openSession();
        UserMapper1 userMapper1=session.getMapper(UserMapper1.class);
        Map<String,Object> map=new HashMap<>();
        map.put("address","北京");
        List<User> userList=userMapper1.selectMap(map);
        userList.forEach(System.out::println);
        session.commit();
        session.close();
        is.close();
    }

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜到极致就是渣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值