Mybatis学习 — 动态SQL、注解动态SQL

目录

动态SQL

搭建环境

if 、where

set

choose

SQL片段

Foreach

总结

注解动态SQL


动态SQL

什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句。

官方解释:

搭建环境

新建一个数据库表:blog

//字段:id,title,author,create_time,views

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 '浏览量'
);

1.创建Mybatis基础工程

2.IDutil工具类

import java.util.UUID;

//产生随机ID
public class IDUtil {
    public static String getId(){
        return UUID.randomUUID().toString().replaceAll("-","");
    }
}

3.编写实体类

public class Blog {
    private String id;
    private String title;
    private String author;
    private Date creatTime;//属性名和字段名不一致   驼峰命名
    private int views;
    //get set 构造
}

4.编写Mapper接口及XML文件

//BlogMapper接口
public interface BlogMapper {

}
//BlogMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.damin.dao.BlogMapper">

</mapper>

5.mybatis核心配置文件

    <settings>
        <!--    标准的日志工厂实现-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--    是否开启自动驼峰命名规则映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <mappers>
        <mapper class="com.damin.dao.BlogMapper"/>
    </mappers>

6.插入初始数据

编写接口:

    //插入数据
    int addBlog(Blog blog);

BlogMapper配置文件:

    <insert id="addBlog" parameterType="blog">
        insert into blog (id, title, author, create_time, views)
        values (#{id},#{title},#{author},#{creatTime},#{views});
    </insert>

初始化博客方法:

    @Test
    public void addInitBlog(){
        SqlSession session = MybatisUtils.getSqlSession();
        BlogMapper mapper = session.getMapper(BlogMapper.class);

        Blog blog = new Blog();
        blog.setId(IDUtil.getId());
        blog.setTitle("Mybatis如此简单");
        blog.setAuthor("无敌敏");
        blog.setCreatTime(new Date());
        blog.setViews(9999);

        mapper.addBlog(blog);

        blog.setId(IDUtil.getId());
        blog.setTitle("Java如此简单");
        mapper.addBlog(blog);

        blog.setId(IDUtil.getId());
        blog.setTitle("Spring如此简单");
        mapper.addBlog(blog);

        blog.setId(IDUtil.getId());
        blog.setTitle("微服务如此简单");
        mapper.addBlog(blog);

        session.close();
    }

至此,搭建环境及初始化数据完成!

if 、where

需求:根据作者名字和博客名字查询博客!如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名字来查询。

1.编写接口类:

    //查询博客
    List<Blog> queryBlogIF(Map map);

2.编写SQL语句:

    <!-- select * from blog where title = #{title} and author = #{author} -->
    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <if test="title != null">
                and title = #{title}
            </if>
            <if test="author!=null">
                and author=#{author}
            </if>
        </where>

    </select>

3.测试:

    @Test
    public void queryBlogIF(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();
        map.put("title","Java如此简单");
        map.put("author","无敌敏");

        List<Blog> blogs = mapper.queryBlogIF(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

这个"where"标签会知道如果它包含的标签中有返回值的话,它就插入一个"where"。此外,如果标签返回的内容是以 and 或 or 开头的,则它会自动去除。

set

同理,上面的对于查询SQL语句包含where标签,在进行更新操作时,使用set标签。

//编写BlogMapper接口

    //更新博客
    int UpDateBlog(Map map);

//编写BlogMapper.xml

    <update id="UpDateBlog" parameterType="map">
        update blog
        <set>
            <if test="title != null">
                title = #{title},
            </if>
            <if test="author != null">
                author = #{author}
            </if>
        </set>
        where id = #{id}
    </update>

//测试

    @Test
    public void UpDateBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","Mybatis如此简单2");
        //注意这里的id是随机生成的,而不是平时写的1 2 3...
        map.put("id","1f6825639436460cb83617df57b7bafd");
        mapper.UpDateBlog(map);

        sqlSession.close();
    }

    

choose

有的时候,我们不想用到所有的查询条件,指向选择其中的一个,查询条件有一个满足即可,使用choose变迁可以解决此类问题,类似于Java中地switch语句。

//编写BlogMapper接口

    List<Blog> queryBlogChoose(Map map);

//编写BlogMapper.xml

    <select id="queryBlogChoose" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <choose>
                <when test="title != null">
                    title = #{title}
                </when>
                <when test="author != null">
                   and author = #{author}
                </when>
                <otherwise>
                    and views = #{views}
                </otherwise>
            </choose>
        </where>
    </select>

//测试

    @Test
    public void queryBlogChoose(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        map.put("title","Mybatis如此简单");
        map.put("author","无敌敏");
        map.put("views",9999);

        List<Blog> blogs = mapper.queryBlogChoose(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

SQL片段

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

提取SQL片段:

<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>

引用SQL片段:

<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
        <include refid="if-title-author"></include>
        <!-- 在这里还可以引用其他的 sql 片段 -->
    </where>
</select>

Foreach

也就是对集合进行遍历

需求:我们需要查询blog表中id分别为1,2,3的博客信息(注意:在添加博客信息时,使用了工具类IDUtil,所以id并不是1 2 3,而是随机的,我在这里是先查询了其中三个博客的id拿来用的,为了方便也可以把ID改回1 2 3)

//编写BlogMapper接口

    List<Blog> queryBlogForeach(Map map);

//编写BlogMapper.xml

    <select id="queryBlogForeach" parameterType="map" resultType="blog">
        select * from blog
        <where>
            <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
                id=#{id}
            </foreach>
        </where>
    </select>

//测试

    @Test
    public void queryBlogForeach(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
        HashMap map = new HashMap();
        ArrayList<String> ids = new ArrayList<String>();
        ids.add("1f42bd60580149f0ab8149e150341e46");
        map.put("ids",ids);

        List<Blog> blogs = mapper.queryBlogForeach(map);

        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

           注意:下面这条语句中open="and (",and 和 ( 之间是有一个空格的,不要忘记写,不然会报错。

总结

其实 sql 语句的编写往往就是一个拼接的问题,为了保证拼接准确,我们最好先把原生的sql语句写出来,然后再通过 mybatis 动态SQL对照着改,防止出错。

日常感谢“狂神”老师!

 

注解动态SQL

mybatis的注解也支持动态SQL。mybatis提供了各种注解,如@InsertProvider、@UpdateProvider、@DeleteProvider和@SelectProvider,来帮助构建动态SQL语句。

以上四个Provider注解都有type属性,该属性指定了一个类。method属性,指定该类的方法,其用来提供需要执行的SQL语句。传统的使用字符串拼接的方法构建SQL语句是非常困难的,并且容易出错。所有mybatis提供了一个SQL工具类org.apache.ibatis.jdbc.SQL,该类不适用字符串拼接的方式,并且会以合适的空格前缀和后缀来构造SQL语句。

    //动态查询
    @SelectProvider(type = DeptDynaSqlProvider.class,method = "selectWhitParam")
    List<Dept> selectByPage(Map<String,Object> params);
    //分页动态查询
    public String selectWhitParam(final Map<String,Object> params){
        String sql = new SQL(){
            {
                SELECT("*");
                FROM(DEPTTABLE);
                if (params.get("dept") != null) {
                    Dept dept = (Dept) params.get("dept");
                    if (dept.getName() != null && !dept.getName().equals("")) {
                        WHERE(" name LIKE CONCAT ('%', #{dept.name},'%') ");
                    }
                }
            }
        }.toString();
        if (params.get("pageModel") != null){
            sql += " limit #{pageModel.firstLimitParam} , #{pageModel.pageSize} ";
        }
        return sql;
    }

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值