MyBatis动态SQL

项目的创建和之前一样,具体的看之前的文章,整体结构就是这样

一、if

对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片断拼接到其所在的 SQL 语句中。
语法:<if test=”条件”> sql 语句的部分 </if>

接口方法:StudentDao

// 动态的sql时,使用java对象作为参数
    List<Student> selectStudentIf(Student student);

mapper文件:StudentDao.xml

    <!--if的使用
         <if test="使用的参数为java对象属性值作为判断条件">
         语法:属性=xxx值
    -->

    <!-- 
	注意,当这样写的时候,name不满足而age满足的时候会出现问题
    正常:select id,name,age,email from student where name = ? or age > ?
    不正常: select id,email from student where or age > ? 
	这个时候会有语法错误
    所以写的是时候要在where后面这样
    where 1=1
    这样写的话即使name不满足,后面的也不不会出现语法错误
    select id,email from student where 1=1 or age > ?
    但这样也会出现其他的bug,因为是or,并且1=1永远为true,所以age无论传入多大都会有数据的
    -->
    <select id="selectStudentIf" resultType="com.md.domain.Student">

      select id,email from student
      where 1=1
      <if test="name != null and name != '' ">
          name = #{name}
      </if>

      <if test="age > 0" >
          or age > #{age}
      </if>

    </select>

测试

    @Test
    public void testSelectStudentIf(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        Student student = new Student();
        student.setAge(20);
        
        List<Student> studentList = dao.selectStudentIf(student);
        studentList.forEach(stu-> System.out.println(stu));
		sqlSession.close();

    }

此时即使数据库中,无论年纪多大的都会被查出来,所以就有了下面的标签

二、where

<if/>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 1=1 的子句。因为,若 where 后
的所有<if/>条件均为 false,而 where 后若又没有 1=1 子句,则 SQL 中就会只剩下一个空的 where,SQL
出错。所以,在 where 后,需要添加永为真子句 1=1,以防止这种情况的发生。但当数据量很大时,会
严重影响查询效率

使用<where/>标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加where 子句。需要注意的是,第一个<if/>标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and 去掉。但其它<if/>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错

<where> 用来包含 多个<if>的, 当多个if有一个成立的, <where>会自动增加一个where关键字,并去掉 if中多余的 and ,or等

语法:<where> 其他动态 sql </where>

接口方法

// 动态的sql时,使用java对象作为参数
    List<Student> selectStudentWhere(Student student);

mapper

 <!--where的使用

        select id,email from student WHERE name = ? or age > ?
        select id,email from student WHERE age > ?
        这样就避免了上面的bug
    -->

    <select id="selectStudentWhere" resultType="com.md.domain.Student">

      select id,email from student
      <where>
          <if test="name != null and name != '' ">
              name = #{name}
          </if>

          <if test="age > 0" >
              or age > #{age}
          </if>

      </where>

    </select>

测试:

 @Test
    public void testSelectStudentWhere(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        Student student = new Student();
        student.setName("白昊天");
        student.setAge(20);

        List<Student> studentList = dao.selectStudentWhere(student);
        studentList.forEach(stu-> System.out.println(stu));
        sqlSession.close();


    }

此时就不会出现之前的bug了

三、foreach

<foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意:

  • collection 表示要遍历的集合类型,list ,array 等。
  • open、close、separator 为对遍历内容的 SQL 拼接

语法

<foreach collection=" 集合类型" open=" 开始的字符" close=" 结束的字符"
item=" 集合中的成员" separator=" 集合成员之间的分隔符">
#{item 的值}
</foreach>

例子,查询学号1001、1002、1003学生的信息

如果是用纯java来拼接这个查询sql语句

@Test
    public void testfor(){
        List<Integer> list = new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);

        String sql = "select * from student where id in";

        StringBuilder builder = new StringBuilder("");


        // 添加开始
        builder.append("(");
        for (Integer i : list){
            builder.append(i).append(",");
        }
        // 因为最后多添加了一个逗号,所以在这里进行删除
        builder.deleteCharAt(builder.length()-1);

        builder.append(")");

        sql = sql + builder.toString();
        System.out.println(sql);

//        select * from student where id in(1001,1002,1003)

    }

1. 用法一

接口

// 传入的是普通list
List<Student> selectForeachOne(List<Integer> idlist);

mapper

select id,email from student where id in ( ?,?,? )

<select id="selectForeachOne" resultType="com.md.domain.Student">

      select id,email from student where id in
      <foreach collection="list" item="myid" open="(" close=")" separator=",">

        #{myid}

      </foreach>
    </select>

测试:

 @Test
    public void testSelectForeachOne(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        List<Integer> list = new ArrayList<>();
        list.add(1001);
        list.add(1002);
        list.add(1003);

        List<Student> studentList = dao.selectForeachOne(list);
        studentList.forEach(stu-> System.out.println(stu));

        sqlSession.close();
    }

2. 用法二

接口

//    foreach 用法二 , 传入的是对象集合
    List<Student> selectForeachTwo(List<Student> stulist);

mapper文件

由于传入的是对象,所以要用对象.属性

<select id="selectForeachTwo" resultType="com.md.domain.Student">

        select id,email from student where id in
        <foreach collection="list" item="stu" open="(" close=")" separator=",">
            #{stu.id}
        </foreach>

    </select>

测试方法

    @Test
    public void testSelectForeachTwo(){

        SqlSession sqlSession = MybatisUtils.getSqlSession();
        StudentDao dao = sqlSession.getMapper(StudentDao.class);

        List<Student> students = new ArrayList<>();
        Student stu1 = new Student();
        stu1.setId(1003);
        students.add(stu1);

        List<Student> studentList = dao.selectForeachTwo(students);
        studentList.forEach(stu-> System.out.println(stu));
//        select id,email from student where id in ( ? )
//        Student{id=1003,name='白昊天',email='ht@qq.com',age=18}
        sqlSession.close();
    }

当然了,对于mapper文件的sql语句还可以这样写

<!-- 直接在外面写小括号,只有能凑成完成的sql语句就行-->
    <select id="selectForeachTwo" resultType="com.md.domain.Student">

        select id,email from student where id in (
        <foreach collection="list" item="stu" separator=",">
            #{stu.id}
        </foreach>
        )
    </select>

效果和上面的是一样的,能完成的拼凑出sql语句即可

四、sql代码片段

<sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。

而其它标签使用该 SQL 片断,需要使用<include/>子标签。该<sql/>标签可以定义 SQL 语句中的任何部分,所以<include/>子标签可以放在动态 SQL的任何位置

接口方法:

List<Student> selectStudentSqlFragment(List<Student> stuList);

mapper文件

<!-- 创建 sql 片段 id: 片段的自定义名称 -->
<sql id="studentSql">
	select id,email,age from student
</sql>
<select id="selectStudentSqlFragment" resultType="com.md.domain.Student">
<!-- 引用 sql 片段 -->
	<include refid="studentSql"/>
	<if test="list !=null and list.size > 0 ">
	where id in
	<foreach collection="list" open="(" close=")"
		item="stuobject" separator=",">
	#{stuobject.id}
	</foreach>
<	/if>
</select>

测试方法

@Test
public void testSelectSqlFragment() {
	List<Student> list = new ArrayList<>();
	Student s1 = new Student();
	s1.setId(1002);
	list.add(s1);
	s1 = new Student();
	s1.setId(1005);
	list.add(s1);
	List<Student> studentList = studentDao.selectStudentSqlFragment(list);
	studentList.forEach( stu -> System.out.println(stu));
}

五、总结

根据条件能够使用不同的sql语句,使用mybatis标签

1. if

判断条件,条件为true,就会把if之前的sql加入到主sql语句之后

2. where

<where> 标签里面多个if标签,如果有一个if判断为true,就会在sql的后面加入where关键字,而还会自动的去掉无用的and、or等字符

3. foreach

循环数组,list集合,主要看语法格式

4. sql代码片段

复用常用的sql语句

  • 先定义<sql id="自定义名唯一" > sql语句 </sql>
  • 再使用 <include refid = "id的值">

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


1.pom.xml引入依赖 &lt;dependency&gt; &lt;groupId&gt;com.github.pagehelper&lt;/groupId&gt; &lt;artifactId&gt;pagehelper&lt;/artifactId&gt; &lt;version&gt;5
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt; &lt;!DOCTYPE configuration PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot; &qu
准备工作 ① 创建数据库&amp;数据表 ## 创建数据库 CREATE DATABASE `dbtest1`; ## 创建数据表 CREATE TABLE `t_user` ( `id` INT NOT NULL AUTO_INCREMENT, `username` VARCHAR(20) DEF
MyBatis逆向工程是指根据数据库表结构自动生成对应的实体类、Mapper接口以及SQL映射文件的过程。这个过程可以通过MyBatis提供的逆向工程工具来完成,极大地方便了开发人员,避免了重复的代码编写,提高了开发效率。 创建逆向工程的步骤 1、添加依赖&amp;插件 &lt;!-- 控制Mave
MyBatis获取参数值的两种方式:${}和#{} ${}的本质就是字符串拼接,#{}的本质就是占位符赋值。 ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号;但是#{}使用占位符赋值的方式拼接sql,此时为字符串类型或日期类型的字段进行赋值时,可以自
resultMap作用是处理数据表中字段与java实体类中属性的映射关系。 准备工作 ① 创建数据库&amp;数据表 CREATE DATABASE `dbtest1`; CREATE TABLE `t_emp` ( `emp_id` int NOT NULL AUTO_INCREMENT, `em
EHCache缓存针对于MyBatis的二级缓存。 MyBatis默认二级缓存是SqlSessionFactory级别的。 添加依赖 &lt;!-- MyBatis-EHCache整合包 --&gt; &lt;dependency&gt; &lt;groupId&gt;org.mybatis.cac
MyBatis 提供了一级缓存和二级缓存的支持,用于提高数据库查询的性能,减少不必要的数据库访问。 一级缓存(SqlSession 级别的缓存) 一级缓存是 MyBatis 中最细粒度的缓存,也称为本地缓存。它存在于每个 SqlSession 的生命周期中,当 SqlSession 被关闭或清空时,
动态SQL是 MyBatis 中非常强大且灵活的功能,允许你根据不同的条件构建SQL查询。 这主要通过 &lt;if&gt;、&lt;choose&gt;、&lt;when&gt;、&lt;otherwise&gt;、&lt;foreach&gt;等标签实现。 查询场景 /** * 根据条件查询员工
本教程操作系统:windows10系统、DELL G3电脑。 MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。在 MyBatis 中,配置数据库连接是非常重要的第一步。下面将详细介绍如何配置 MyBatis 的
今天小编给大家分享的是MyBatis批量查询、插入、更新、删除如何实现,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。
今天小编给大家分享的是Mybatis操作多数据源实现的方法,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
本篇文章和大家了解一下mybatis集成到spring的方式有哪些。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。1 前言1.1 集成spring前使用mybat...
今天小编给大家分享的是mybatis-plus分页查询的3种方法,相信很多人都不太了解,为了让大家更加了解,所以给大家总结了以下内容,一起往下看吧。一定会有所收获...
本篇内容主要讲解“mybatis之BaseTypeHandler怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“mybatis...
这篇文章主要介绍了mybatisforeach怎么传两个参数的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇mybatisforeach怎...
这篇“MyBatis映射文件中parameterType与resultType怎么使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的...
这篇文章主要介绍“MyBatis怎么获取自动生成的键值”,在日常操作中,相信很多人在MyBatis怎么获取自动生成的键值问题上存在疑惑,小编查阅了各式资料,整理出
这篇文章主要讲解了“怎么去掉IntelliJIDEA中mybatis对应的xml文件警告”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入...
这篇文章主要介绍“MybatisPlus使用@TableId主键id自增长无效如何解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这...