MyBatis介绍(四) 动态sql

本文介绍了MyBatis中动态SQL的使用,包括if进行条件查询,choose(when, otherwise)实现类似Java switch的效果,trim结合if解决where与and问题,以及where简化条件判断。每个部分都通过实例展示了其优点和注意事项。" 111579918,10295374,向量时钟:分布式系统的因果关系判断,"['分布式系统', '向量时钟同步算法', '逻辑时钟', '数据一致性']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.动态sql
1.使用if 条件查询
(1) 创建数据库和表

CREATE TABLE `t_blog` (
    `id` INT (11),
    `title` VARCHAR (765),
    `content` VARCHAR (765),
    `owner` VARCHAR (150)
); 
INSERT INTO `t_blog` (`id`, `title`, `content`, `owner`) VALUES('1','java基础','详细描述','唐国强11');
INSERT INTO `t_blog` (`id`, `title`, `content`, `owner`) VALUES('2','中文','中国','ofo11');
INSERT INTO `t_blog` (`id`, `title`, `content`, `owner`) VALUES('3','html','html标签','样式');
INSERT INTO `t_blog` (`id`, `title`, `content`, `owner`) VALUES('6','html','www','eee');
INSERT INTO `t_blog` (`id`, `title`, `content`, `owner`) VALUES('9','中文','111','1111');

(2)实体类Blog

public class Blog {
    private int id;
    private String title;
    private String content;
    private String owner;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }
    public void setContent(String content) {
        this.content = content;
    }

    public String getOwner() {
        return owner;
    }
    public void setOwner(String owner) {
        this.owner = owner;
    }

    @Override
    public String toString() {
        return "Blog{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", owner='" + owner + '\'' +
                '}';
    }
}

(3)定义sql映射文件BlogMapper.xml

<?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="me.gacl.mapping.BlogMapper">//命名空间

    <select id="getBlogByIf" parameterType="Blog" resultType="Blog">
        select * from t_blog **where 1=1** //必须加where语句 
        <if test="title !=null">
            and  title=#{title}
        </if>
        <if test="content !=null">
            and content=#{title}
        </if>
        <if test="owner !=null">
            and owner=#{owner}
        </if>
    </select>

</mapper>

(4).工具类MyBatisUtil

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.InputStream;

public class MyBatisUtil {

    public static SqlSessionFactory getSqlSessionFactory(){
        /*
        * 获取SqlSessionFactory
        * */
        String resource = "conf.xml";
        InputStream is = MyBatisUtil.class.getClassLoader().getResourceAsStream(resource);
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
        return factory;
    }
    public static SqlSession getSqlSession(){
        return getSqlSessionFactory().openSession();
    }
    /**
     * 获取SqlSession
     * @param isAutoCommit
     *         true 表示创建的SqlSession对象在执行完SQL之后会自动提交事务
     *         false 表示创建的SqlSession对象在执行完SQL之后不会自动提交事务,这时就需要我们手动调用sqlSession.commit()提交事务
     * @return SqlSession
     */

    public static SqlSession getSqlSession(boolean isAutoCommit){
        return getSqlSessionFactory().openSession(isAutoCommit);
    }
}

(5)在conf.xml中注册BlogMapper.xml文件

    <mappers>
          <mapper resource="me/gacl/mapping/BlogMapper.xml"/>
    </mappers>

(6)编写测试类TestBlog

public class TestBlog {

    @Test
    public void testGetBlogIf(){
        SqlSession sqlSession= MyBatisUtil.getSqlSession();
        String statement="me.gacl.mapping.BlogMapper.getBlogByIf";
        Blog blog=new Blog();
        blog.setTitle("html");
        List<Blog> blogList=sqlSession.selectList(statement,blog);
        System.out.println(blogList);

    }

}

执行结果为:
[Blog{id=3, title=’html’, content=’html标签’, owner=’样式’},
Blog{id=6, title=’html’, content=’www’, owner=’eee’}]**

优点:
这条语句的意思非常简单,如果你提供了title参数,那么就要满足title=#{title},同样如果你提供了Content和Owner的时候,它们也需要满足相应的条件,之后就是返回满足这些条件的所有Blog,这是非常有用的一个功能,以往我们使用其他类型框架或者直接使用JDBC的时候, 如果我们要达到同样的选择效果的时候,我们就需要拼SQL语句,这是极其麻烦的,比起来,上述的动态SQL就要简单多了
缺点:
sql语句必须加where语句 否则很难判断where与and的问题

2.使用choose(when,otherwise)查询
(1).在BlogMapper.xml中编写代码

 <select id="getBlogByChoose" parameterType="Blog" resultType="Blog">
        select * from t_blog where 1=1
        <choose> <!--相当于Java中的switch语句-->
          <when test="title !=null">
               and title=#{title}
          </when>
          <when test="content !=null">
                and content=#{title}
           </when>
          <otherwise>
                and owner="owner1"
          </otherwise>
        </choose>
    </select>

(2).编写测试代码

 @Test
    public void testGetBlogChoose(){
        SqlSession sqlSession= MyBatisUtil.getSqlSession();
        String statement="me.gacl.mapping.BlogMapper.getBlogByChoose";
        Blog blog=new Blog();
        blog.setTitle("html");
        blog.setContent("www");
        List<Blog> blogList=sqlSession.selectList(statement,blog);
        System.out.println(blogList);

    }

执行结果为:
[Blog{id=3, title=’html’, content=’html标签’, owner=’样式’},
Blog{id=6, title=’html’, content=’www’, owner=’eee’}]
优点:
when元素表示当when中的条件满足的时候就输出其中的内容,跟JAVA中的switch效果差不多的是按照条件的顺序,当when中有条件满足的时候,就会跳出choose,即所有的when和otherwise条件中,只有一个会输出,当所有的我很条件都不满足的时候就输出otherwise中的内容。所以上述语句的意思非常简单, 当title!=null的时候就输出and titlte = #{title},不再往下判断条件,当title为空且content!=null的时候就输出and content = #{content},当所有条件都不满足的时候就输出otherwise中的内容。
缺点:
当所有条件都不满足的时候就输出otherwise中的内容。

注意:与Java的switch不同的是choose是当when中有条件满足的时候,就会跳出choose

3.使用if+trim(对包含的内容加上 prefix,或者 suffix 等,前缀,后缀)
(1).在BlogMapper.xml中编写代码

 <select id="getBlogByTrim" parameterType="Blog" resultType="Blog">
        select * from t_blog
        <trim prefix="where" prefixOverrides="and|or">
            <if test="title !=null">
                title=#{title}
            </if>
            <if test="content !=null">
                and content=#{content}
            </if>
            <if test="owner !=null">
               or owner=#{owner}
            </if>
        </trim>
    </select>

(2).编写测试代码

 @Test
    public void testGetBlogTrim(){
        SqlSession sqlSession= MyBatisUtil.getSqlSession();
        String statement="me.gacl.mapping.BlogMapper.getBlogByTrim";
        Blog blog=new Blog();
        blog.setTitle("html");
        blog.setContent("www");
        blog.setOwner("样式");
        List<Blog> blogList=sqlSession.selectList(statement,blog);
        System.out.println(blogList);

    }

执行结果为:
[Blog{id=3, title=’html’, content=’html标签’, owner=’样式’},
Blog{id=6, title=’html’, content=’www’, owner=’eee’}]
优点:
trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能
主要是解决了上述if的where与and难题

4.where (主要是用来简化sql语句中where条件判断的,能智能的处理 and or 条件)
(1).在BlogMapper.xml中编写代码

 <select id="getBlogByWhere" parameterType="Blog" resultType="Blog">
        select * from t_blog
        <where>
            <!--MyBatis会智能的把首个and 或 or 给忽略 在where元素中你不需要考虑空格的问题-->
            <if test="title !=null">
              title=#{title}
            </if>
            <if test="content !=null">
                and content=#{content}
            </if>
            <if test="owner !=null">
                and owner=#{owner}
            </if>
        </where>

(2).编写测试代码

 @Test
    public void testGetBlogWhere(){
        SqlSession sqlSession= MyBatisUtil.getSqlSession();
        String statement="me.gacl.mapping.BlogMapper.getBlogByWhere";
        Blog blog=new Blog();
        //blog.setTitle("html");
        blog.setContent("www");
        List<Blog> blogList=sqlSession.selectList(statement,blog);
        System.out.println(blogList);

    }

执行结果为:
[Blog{id=6, title=’html’, content=’www’, owner=’eee’}]
优点:
where元素的作用是会在写入where元素的地方输出一个where,另外一个好处是你不需要考虑where元素里面的条件输出是什么样子的,MyBatis会智能的帮你处理,如果所有的条件都不满足那么MyBatis就会查出所有的记录,如果输出后是and 开头的,MyBatis会把第一个and忽略,当然如果是or开头的,MyBatis也会把它忽略;此外,在where元素中你不需要考虑空格的问题,MyBatis会智能的帮你加上。像上述例子中,如果title=null, 而content != null,那么输出的整个语句会是select * from t_blog where content = #{content},而不是select * fr**om t_blog where and content = #{content},因为MyBatis会智能的把首个and 或 or 给忽略
注意:
trim和where实现的功能一样
5.set (主要用于更新时)
(1).在BlogMapper.xml中编写代码

 <update id="updateBySet" parameterType="Blog">
        update t_blog
        <set> 
            <if test="title!=null">
                title=#{title}, 
            </if>
            <if test="content!=null">
                content=#{content},
            </if>
            <if test="owner!=null">
                owner=#{owner}
            </if>
        </set>
        where id=#{id}
    </update>

(2).编写测试代码

 @Test
    public void testUpdateBySet(){
        SqlSession sqlSession= MyBatisUtil.getSqlSession(true);
        String statement="me.gacl.mapping.BlogMapper.updateBySet";
        Blog blog=new Blog();
        blog.setId(6);
        blog.setTitle("html");
        blog.setContent("www");
        int result=sqlSession.update(statement,blog);
        System.out.println(result);

    }

执行结果为: 1

优点:
set元素主要是用在更新操作的时候,它的主要功能和where元素其实是差不多的,主要是在包含的语句前输出一个set,然后如果包含的语句是以逗号结束的话将会把该逗号忽略,如果set包含的内容为空的话则会出错。有了set元素我们就可以动态的更新那些修改了的字段

**注意:
(1)前两个条件加逗号 后一个不用
(2)set包含的内容不能为空
(3)加where语句**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值