MyBatis——动态SQL的四个常用标签(<if>、<where>、<foreach>、<sql>)

简介: MyBatis——动态SQL的四个常用标签(<if>、<where>、<foreach>、<sql>)

文章目录:


1.什么是动态SQL 

2.MyBatis中的动态SQL

2.1 动态SQL——if标签

2.1.1 语法格式 

2.1.2 应用举例

2.2 动态SQL——where标签

2.2.1 语法格式 

2.2.2 应用举例

2.3 动态SQL——foreach标签

2.3.1 语法格式

2.3.2 应用举例1(简单类型)

2.3.2 应用举例2(对象类型)

2.4 动态SQL——sql标签

2.4.1 语法格式 

2.4.2 应用举例

1.什么是动态SQL?


动态 SQL,通过MyBatis提供的各种标签对条件作出判断以实现动态拼接SQL 语句。这里的条件判断使用的表达式为 OGNL 表达式。常用的动态 SQL标签有<if><where><foreach><sql>等。

MyBatis的动态 SQL 语句,与 JSTL 中的语句非常相似。

动态 SQL,主要用于解决查询条件不确定的情况:在程序运行期间,根据用户提交的查询条件进行查询。提交的查询条件不同,执行的 SQL 语句不同。若将每种可能的情况均逐一列出,对所有条件进行排列组合,将会出现大量的SQL 语句。此时,可使用动态 SQL 来解决这样的问题。

使用动态SQL时,dao接口中方法的形参要使用Java对象。

2.MyBatis中的动态SQL


2.1 动态SQL——if标签

2.1.1 语法格式 

<if test="boolean判断结果"> <!--要么为true、要么为false--> 
    sql语句的部分 
</if>
<!-- 对于该标签的执行,当 test 的值为 true 时,会将其包含的 SQL 片段断拼接到其所在的 SQL 语句中。 --> 

2.1.2 应用举例

package com.bjpowernode.dao;
import com.bjpowernode.entity.Student;
import java.util.List;
/**
 *
 */
public interface StudentDao {
    //if
    List<Student> selectIf(Student student);
}
<!-- if
     test: 使用对象的属性值作为条件
-->
<select id="selectIf" resultType="com.bjpowernode.entity.Student">
     select *
     from student
     where id=-1
     <if test="name!=null and name!=''">
         or name=#{name}
     </if>
     <if test="age>0">
         or age=#{age}
     </if>
</select>
<!--
    <if/>标签的中存在一个比较麻烦的地方:需要在 where 后手工添加 id=-1的子句。
    因为,若 where 后的所有<if/>条件均为 false,而 where 后若又没有 id=-1 子句,则 SQL 中就会只剩下一个空的 where,SQL 出错。
    所以,在where 后,需要添加子句 id=-1,以防止这种情况的发生。但当数据量很大时,会严重影响查询效率。
-->
    @Test
    public void testSelectIf() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        Student student=new Student();
        student.setName("张起灵");
        student.setAge(20);
        List<Student> students=studentDao.selectIf(student);
        students.forEach( stu -> System.out.println("stu === " + stu) );
        session.close();
    }

根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇 

select *
from student
where id=-1 or name="张起灵" or age=20


2.2 动态SQL——where标签

2.2.1 语法格式 

<where> 
    其他动态sql 
</where>

2.2.2 应用举例

package com.bjpowernode.dao;
import com.bjpowernode.entity.Student;
import java.util.List;
/**
 *
 */
public interface StudentDao {
    //where
    List<Student> selectWhere(Student student);
}
    <!-- where -->
    <select id="selectWhere" resultType="com.bjpowernode.entity.Student">
        select *
        from student
        <where>
            <if test="name!=null and name!=''">
                or name=#{name}
            </if>
            <if test="age>0">
                or age=#{age}
            </if>
        </where>
    </select>
<!--
    使用<where/>标签,在有查询条件时,可以自动添加上 where 子句;没有查询条件时,不会添加 where 子句。
    需要注意的是,第一个<if/>标签中的SQL 片断,可以不包含 and。不过,写上 and 也不错,where标签会将离它最近的 and 或者 or 删掉。
    但其它<if/>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
-->
    @Test
    public void testSelectWhere() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        Student student=new Student();
        student.setName("张起灵");
        student.setAge(20);
        List<Student> students=studentDao.selectWhere(student);
        students.forEach( stu -> System.out.println("stu === " + stu) );
        session.close();
    }

根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇  

  select *
 from student
  where id=-1 or name="张起灵" or age=20


2.3 动态SQL——foreach标签

2.3.1 语法格式

<foreach collection="集合类型" open="开始的字符" close="结束的字符" item="集合中的成员" separator="集合成员之间的分隔符">
    #{item的值}
</foreach>
<!--
    如果dao接口中方法的形参是数组,则collection="array"
    如果dao接口中方法的形参是List,则collection="list"
    #item的值}:获取集合成员的值
-->

2.3.2 应用举例1(简单类型)

package com.bjpowernode.dao;
import com.bjpowernode.entity.Student;
import java.util.List;
/**
 *
 */
public interface StudentDao {
    //for-each 1
    List<Student> selectForeachOne(List<Integer> idlist);
}
    <!-- foreach第一种方式,循环简单类型的List: List<Integer> -->
    <select id="selectForeachOne" resultType="com.bjpowernode.entity.Student">
        select *
        from student
        <if test="list!=null and list.size>0">
            where id in
            <foreach collection="list" open="(" close=")" separator="," item="stuid">
                #{stuid}
            </foreach>
        </if>
    </select>
    @Test
    public void testSelectForeachOne() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        List<Integer> idlist=new ArrayList<>();
        idlist.add(1001);
        idlist.add(1002);
        idlist.add(1003);
        List<Student> students=studentDao.selectForeachOne(idlist);
        students.forEach( stu -> System.out.println("stu === " + stu));
        session.close();
    }

根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇  

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


2.3.2 应用举例2(对象类型)

package com.bjpowernode.dao;
import com.bjpowernode.entity.Student;
import java.util.List;
/**
 *
 */
public interface StudentDao {
    //for-each 2
    List<Student> selectForeachTwo(List<Student> studentList);
}
    <!-- foreach第二种方式,循环对象类型的List: List<Student> -->
    <select id="selectForeachTwo" resultType="com.bjpowernode.entity.Student">
        select *
        from student
        <if test="list!=null and list.size>0">
            where id in
            <foreach collection="list" open="(" close=")" separator="," item="stu">
                #{stu.id}
            </foreach>
        </if>
    </select>
    @Test
    public void testSelectForeachTwo() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        List<Student> list=new ArrayList<>();
        Student s1=new Student();
        s1.setId(1001);
        Student s2=new Student();
        s2.setId(1002);
        Student s3=new Student();
        s3.setId(1003);
        list.add(s1);
        list.add(s2);
        list.add(s3);
        List<Student> students=studentDao.selectForeachTwo(list);
        students.forEach( stu-> System.out.println("stu === " + stu));
        session.close();
    }

根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇    

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

2.4 动态SQL——sql标签

2.4.1 语法格式 

<sql id="...">
    sql语句
</sql>
<include refid="sql标签的id属性值"></include>
<!--
    <sql/>标签用于定义 SQL 片断,以便其它 SQL 标签复用。
    而其它标签使用该 SQL 片断,需要使用<include/>子标签。
    该<sql/>标签可以定义 SQL 语句中的任何部分,所以<include/>子标签可以放在动态 SQL 的任何位置。
-->

2.4.2 应用举例

package com.bjpowernode.dao;
import com.bjpowernode.entity.Student;
import java.util.List;
/**
 *
 */
public interface StudentDao {
    //代码片段
    List<Student> selectSql(List<Student> studentList);
}
    <!-- 定义代码片段 -->
    <sql id="selectStudent">
        select id,name,age from student
    </sql>
    <sql id="studentFieldList">
        where id in
    </sql>
    <select id="selectSql" resultType="com.bjpowernode.entity.Student">
        <include refid="selectStudent"></include>
        <if test="list!=null and list.size>0">
            <include refid="studentFieldList"></include>
            <foreach collection="list" open="(" close=")" separator="," item="student">
                #{student.id}
            </foreach>
        </if>
    </select>
    @Test
    public void testSelectSql() {
        SqlSession session = MyBatisUtil.getSqlSession();
        StudentDao studentDao=session.getMapper(StudentDao.class);
        List<Student> list=new ArrayList<>();
        Student s1=new Student();
        s1.setId(1001);
        Student s2=new Student();
        s2.setId(1002);
        Student s3=new Student();
        s3.setId(1003);
        list.add(s1);
        list.add(s2);
        list.add(s3);
        List<Student> students=studentDao.selectSql(list);
        students.forEach( stu-> System.out.println("stu === " + stu));
        session.close();
    }

根据上面三个代码块,将其中的内容转为等价的 sql 语句如下:👇👇👇    

select id,name,age
from student
where id in (1001,1002,1003)

相关文章
|
10月前
|
SQL 数据库 数据安全/隐私保护
SQL查询优化:where子句的高效使用方式
总的来说,如果将 SQL 查询比喻为一个乐团的演奏,WHERE 子句就像是独奏者,它需要各位乐手的协助,才能发挥出最美妙的音乐。计划好你的演奏,挑选对的音符,在最适当的时间开始演奏,那么,你可以更高效地运用 SQL 查询,更好地把握数据的篇章。
224 19
|
10月前
|
SQL 数据库 数据安全/隐私保护
SQL查询优化:where子句的高效使用方式。
总的来说,如果将 SQL 查询比喻为一个乐团的演奏,WHERE 子句就像是独奏者,它需要各位乐手的协助,才能发挥出最美妙的音乐。计划好你的演奏,挑选对的音符,在最适当的时间开始演奏,那么,你可以更高效地运用 SQL 查询,更好地把握数据的篇章。
159 13
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
SQL 关系型数据库 MySQL
惊呆:where 1=1 可能严重影响性能,差了10多倍,快去排查你的 sql
老架构师尼恩在读者交流群中分享了关于MySQL中“where 1=1”条件的性能影响及其解决方案。该条件在动态SQL中常用,但可能在无真实条件时导致全表扫描,严重影响性能。尼恩建议通过其他条件或SQL子句命中索引,或使用MyBatis的`&lt;where&gt;`标签来避免性能问题。他还提供了详细的执行计划分析和优化建议,帮助大家在面试中展示深厚的技术功底,赢得面试官的青睐。更多内容可参考《尼恩Java面试宝典PDF》。
|
SQL XML Java
Mybatis的<where>,<if>等标签用法
这篇文章详细解释了Mybatis中<where>和<if>等标签的用法,展示了如何在SQL动态构建中有效地过滤条件和处理逻辑分支。
918 1
|
SQL XML Java
Mybatis中foreach的使用
【11月更文挑战第12天】MyBatis 的 `foreach` 标签用于在 SQL 语句中遍历集合或数组,支持批量插入、更新及多条件查询等操作。通过设置 `collection`、`item` 等属性,可动态生成 SQL 片段,实现高效的数据处理。示例包括批量插入用户信息、根据 ID 列表查询用户数据以及遍历 Map 查询分类下的产品。
931 0
|
SQL 数据处理 数据库
python 提取出sql语句中where的值
python 提取出sql语句中where的值
242 0
|
SQL 监控 关系型数据库
PolarDB产品使用问题之SQL防火墙怎么拦截没有指定WHERE条件的特定表的SQL语
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
SQL Java 数据库连接
mybatis动态SQL常用语法总结
MyBatis 使用 OGNL 表达式语言处理动态SQL,如 `if` 标签进行条件判断,`choose`、`when`、`otherwise` 实现多条件选择,`where`、`set` 管理SQL关键字,`trim` 提供通用修剪功能,`foreach` 遍历集合数据。`sql` 和 `include` 用于代码重用,`selectKey` 处理插入后的返回值。参数传递支持匿名、具名、列表、Map、Java Bean和JSON方式。注意SQL转义及使用合适的jdbcType映射Java类型。