Mybatis学习记录06——动态SQL

环境搭建

  1. 创建表并插入数据
CREATE TABLE `blog` (
    `id` varchar(50) NOT NULL COMMENT '博客id',
      `title` varchar(100) NOT NULL COMMENT '博客标题',
      `author` varchar(30) NOT NULL COMMENT '博客作者',
      `create_time` datetime NOT NULL COMMENT '创建时间',
      `views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8
  1. 创建实体类
@Data
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;
    private int views;
}
  1. Mapper接口
public interface BlogMapper {
    List<Blog> getAllBlogs();
}
  1. Mapper映射文件
<mapper namespace="com.wcy.dao.BlogMapper">
    <select id="getAllBlogs" resultType="Blog">
        select *
        from blog;
    </select>
</mapper>
  1. mybatis配置文件
<configuration>
    <!--  外部配置文件  -->
    <properties resource="db.properties"/>

    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>

    <!--  别名  -->
    <typeAliases>
        <typeAlias type="com.wcy.pojo.Blog" alias="Blog"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--  自己编写的Mapper接口对应的mapper.xml  -->
    <mappers>
        <mapper resource="com/wcy/dao/BlogMapper.xml"/>
    </mappers>
</configuration>
  1. 测试
@Test
    public void getAllBlogs(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        List<Blog> allBlogs = mapper.getAllBlogs();
        for (Blog blog : allBlogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
这里create出现null是因为数据库中的字段和实体类中的属性不匹配导致的,这里由于他们的区别只是没有用驼峰命名,我们只需要添加一条设置即可

<setting name="mapUnderscoreToCamelCase" value="true"/>

在这里插入图片描述

if语句

使用if语句实现动态查询

List<Blog> getBlogsByIf(Map<String, Object> map);
<select id="getBlogsByIf" resultType="Blog" parameterType="map">
        select * from blog where 1=1
        <!--如果title条件存在 继续加上下面的条件-->
        <if test="title != null">
            and title=#{title}
        </if>
        <!--如果author条件存在 继续加上下面的条件-->
        <if test="author != null">
            and author=#{author}
        </if>
    </select>
@Test
    public void getBlogsByIf(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        List<Blog> blogs = mapper.getBlogsByIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

此时如果不在map中传入任何的参数,能够查询到所有的信息

在这里插入图片描述
如果要查询符合条件的信息,只需要传入对应的kv键值对即可

@Test
    public void getBlogsByIf(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("title", "python");
        map.put("author", "王二");
        List<Blog> blogs = mapper.getBlogsByIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
可以看到对应的sql加上了限制条件

where语句

在上面的例子中,我们在基础sql语句的最后添加了一个条件1=1,这是为了我们在使用if语句拼接的时候可以正确的拼接语句,因为如果不写1=1这个条件,当所有的if条件没有匹配上时,sql语句就会变成下面这个样子

select * from blog where

这样的话sql语句就会报错,所以添加1=1这个条件防止sql语句出错

但是在实际开发中我们不会加上中多余的条件,所以where元素就专门来解决这个问题的,来看看官方说明

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除

用个实例来说明一下,继续用上面的例子

List<Blog> getBlogsByIf(Map<String, Object> map);

将mapper更改一下

<select id="getBlogsByIf" resultType="Blog" parameterType="map">
   select * from blog
    <!--如果where标签中有成立的选项,才会拼接where条件-->
    <where>
        <!--如果title条件存在 继续加上下面的条件-->
        <if test="title != null">
            and title=#{title}
        </if>
        <!--如果author条件存在 继续加上下面的条件-->
        <if test="author != null">
            and author=#{author}
        </if>
    </where>
</select>

接下来测试

  1. 满足第一个条件时
@Test
    public void getBlogsByIf(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        // 传入第一个条件
        map.put("title", "python");
        List<Blog> blogs = mapper.getBlogsByIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
可以看到sql语句拼接了where,并且我们在每一个条件的前面其实都加了and,但是实际的sql语句里面,and已经被去掉了,这就是where的好处,也印证了官方的话

  1. 满足两个条件
@Test
    public void getBlogsByIf(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        // 传入第一个条件和第二个条件
        map.put("title", "python");
        map.put("author", "王二");
        List<Blog> blogs = mapper.getBlogsByIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
结果和想象中的一样,sql语句被正确的拼接了

  1. 没有任何条件时
@Test
    public void getBlogsByIf(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        List<Blog> blogs = mapper.getBlogsByIf(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
可以看到当没有任何条件时,并没有拼接where关键字,查询到了所有的信息

set语句

set和where的用法差不多
set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)

int updateBlog(Map<String, Object> map);
<update id="updateBlog" parameterType="map">
    update blog
    <!--动态拼接set字段-->
    <set>
        <if test="title != null">
            title=#{title}
        </if>
        <if test="author != null">
            author=#{author}
        </if>
        <if test="views != null">
            views=#{views}
        </if>
    </set>
    where id=#{id}
</update>

在这里插入图片描述

trim语句

可以自定义where和set语句

如果 where 元素与你期望的不太一样,你也可以通过自定义 trim 元素来定制 where 元素的功能。比如,和 where 元素等价的自定义 trim 元素为:

<!--and和or后面都有空格-->
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

prefixOverrides 属性会忽略通过管道符分隔的文本序列(注意此例中的空格是必要的)。上述例子会移除所有 prefixOverrides 属性中指定的内容,并且插入 prefix 属性中指定的内容。

来看看与 set 元素等价的自定义 trim 元素吧:

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

注意,我们覆盖了后缀值设置为",",并且自定义了前缀值为set

choose语句

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
编写一个条件查询来试一下

ist<Blog> getBlogsByChoose(Map<String, Object> map);
    <select id="getBlogsByChoose" parameterType="map" resultType="Blog">
        select * from blog
        <where>
            <!--
                choose中只有一个选项能执行
                当when中的条件满足时就会拼接上
                当when中的条件都不满足时会拼接otherwise中的语句
            -->
            <choose>
                <when test="id != null">
                    id=#{id}
                </when>
                <when test="title != null">
                    title=#{title}
                </when>
                <when test="author != null">
                    author=#{author}
                </when>
                <otherwise>
                    <!--这里什么也不做 不存在条件就查询全部-->
                </otherwise>
            </choose>
        </where>
    </select>

SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        map.put("views", 6666);
        map.put("id", 1);
        int i = mapper.updateBlog(map);
        System.out.println(i);
        session.close();

在这里插入图片描述
可以看到 传入id后,满足了第一个条件,并没有加上views条件

来看一下什么都不传的情况

@Test
    public void getBlogsByChoose(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        Map<String, Object> map = new HashMap<>();
        List<Blog> blogs = mapper.getBlogsByChoose(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述
确实没有添加条件,查询到了全部的信息

sql片段

有时候可能某个 sql 语句我们用的特别多,为了增加代码的重用性,简化代码,我们需要将这些代码抽取出来,然后使用时直接调用。使用sql标签即可完成

<select id="getBlogsByIf" resultType="Blog" parameterType="map">
  select * from blog
    <!--如果where标签中有成立的选项,才会拼接where条件-->
    <where>
        <!--使用include来引入sql片段-->
        <include refid="condition"/>
    </where>
</select>

<!--  使用sql标签提取出sql片段  -->
<sql id="condition">
    <!--如果title条件存在 继续加上下面的条件-->
    <if test="title != null">
        and title=#{title}
    </if>
    <!--如果author条件存在 继续加上下面的条件-->
    <if test="author != null">
        and author=#{author}
    </if>
</sql>

foreach语句

foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符,看它多智能!

提示 你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

例如用一个多条件查询来实现这个例子

select * from blog where (id=1 or id=2 or id=3)

在这个sql语句中,我们用foreach来动态添加括号内的条件,只需要传入一个id数组即可

List<Blog> getBlogsByForeach(Map<String, Object> map);
<select id="getBlogsByForeach" parameterType="map" resultType="Blog">
   select * from blog
   <where>
       <!--
           collection->被遍历的集合 意味着我们需要在map中put一个名为ids的集合
           item->每一个被遍历项目的名字
           index->被遍历的索引名
           open->开始符号
           separator->分隔符号
           close->结尾符号
       -->
       <foreach collection="ids" item="id" index="index" open="(" separator="or" close=")">
           id=#{id}
       </foreach>
   </where>
</select>

当传入参数时,拼接条件

@Test
    public void getBlogsByForeach(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        ArrayList<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        map.put("ids", ids);
        List<Blog> blogs = mapper.getBlogsByForeach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述

传入空列表时,默认查询全部

 @Test
    public void getBlogsByForeach(){
        SqlSession session = MybatisUtil.getSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);
        HashMap<String, Object> map = new HashMap<>();
        ArrayList<Integer> ids = new ArrayList<>();
        map.put("ids", ids);
        List<Blog> blogs = mapper.getBlogsByForeach(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        session.close();
    }

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值