首页 数据库 SQL 学习MyBatis 动态 SQL

学习MyBatis 动态 SQL

Dec 09, 2020 pm 05:46 PM
mybatis sql

sql教程介绍SQL MyBatis的强大特性SQL

学习MyBatis 动态 SQL

推荐(免费):sql教程

动态 SQL

MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。

虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。

动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

准备

首先创建User实体类

public class User {
    private Integer id;
    private String username;
    private String userEmail;
    private String userCity;
    private Integer age;}
登录后复制

创建user表

CREATE TABLE user (
  id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(255) DEFAULT NULL,
    user_email varchar(255) DEFAULT NULL,
    user_city varchar(255) DEFAULT NULL,
    age int(11) DEFAULT NULL,
  PRIMARY KEY (id))
登录后复制

if

定义接口方法

public List<User> findByUser(User user);
登录后复制

接口对应的 Mapper.xml 定义如下所示

<select id="findByUser" resultType="com.example.mybatis.entity.User">
    select
    id, username, user_email userEmail, user_city userCity, age
    from user
    where    <if test="username != null and username != &#39;&#39;">
        username = #{username}    </if>
    <if test="userEmail != null and userEmail != &#39;&#39;">
        and user_email = #{userEmail}    </if>
    <if test="userCity != null and userCity != &#39;&#39;">
        and user_city = #{userCity}    </if></select>
登录后复制

如果if标签上的test为true,那么if标签里面的SQL语句将会被拼接。

如果username、userEmail、userCity都不为空,那么SQL将会拼接成如下所示

select id, username, user_email userEmail, user_city userCity, age 
from user where username = ? and user_email = ? and user_city = ?
登录后复制

如果只有username不为空,那么SQL将会拼接成如下所示

select id, username, user_email userEmail, user_city userCity, age 
from user where username = ?
登录后复制

但是这种方式存在一个缺点,假设此时username为空,userEmail、userCity都不为空。

我们来分析动态 SQL 代码,现在没有给 username 赋值,即 username==null,所以 “username=#{username}” 这段代码不会添加到 SQL 语句中,那么最终拼接好的动态 SQL 是这样的:

select id, username, user_email userEmail, user_city userCity, age 
from user where and user_email = ? and user_city = ?
登录后复制

where 后面直接跟 and,很明显的语法错误,此时应该把紧跟在where后面的and删掉。为了解决这个问题,可以使用where标签。

where

将上面的SQL改成如下所示

    <select id="findByUser" resultType="com.example.mybatis.entity.User">
        select
        id, username, user_email userEmail, user_city userCity, age        from user
        <where>
            <if test="username != null and username != &#39;&#39;">
                username = #{username}
            </if>
            <if test="userEmail != null and userEmail != &#39;&#39;">
                and user_email = #{userEmail}
            </if>
            <if test="userCity != null and userCity != &#39;&#39;">
                and user_city = #{userCity}
            </if>
        </where>
    </select>
登录后复制

如果where标签里面的if标签有满足条件的,那么where标签就会被拼接成where语句,若if标签拼接的SQL最前面有and语句,那么这个and将会被删除。使用这种方法, 会自动删除SQL中不需要的关键字,所以一般 if 标签和 where 标签会组合起来使用。

trim

trim标签中的 prefixsuffix属性会被用于生成实际的 SQL 语句,会和标签内部的语句拼接。

如果语句的前面或后面遇到 prefixOverridessuffixOverrides属性中指定的值,MyBatis 会自动将它们删除。在指定多个值的时候,别忘了每个值后面都要有一个空格,保证不会和后面的 SQL 连接在一起。

prefix:给拼接的SQL语句加一个前缀

suffix:给拼接的SQL语句加一个后缀

prefixOverrides:拼接的SQL语句前面遇到 prefixOverrides,MyBatis 会自动将它们删除

suffixOverrides:拼接的SQL语句后面遇到 suffixOverrides,MyBatis 会自动将它们删除

下面使用trim标签来实现where标签的功能

<select id="findByUser" resultType="com.example.mybatis.entity.User">
        select
        id, username, user_email userEmail, user_city userCity, age
        from user        <trim prefix="where" prefixOverrides="and">
            <if test="username != null and username != &#39;&#39;">
                username = #{username}            </if>
            <if test="userEmail != null and userEmail != &#39;&#39;">
                and user_email = #{userEmail}            </if>
            <if test="userCity != null and userCity != &#39;&#39;">
                and user_city = #{userCity}            </if>
        </trim>
    </select>
登录后复制

如果username为空,userEmail和userCity不为空,那么if 标签拼接的SQL语句如下所示

and user_email = #{userEmail} and user_city = #{userCity}
登录后复制

因为trim标签设置了prefixOverrides=”and”,而上面的SQL前面有and语句,所以需要将上面的and语句删掉,又因为trim标签设置了prefix=”where”,所以需要在拼接的SQL语句前面加一个where语句

最后trim标签的SQL语句被拼接成如下所示

where user_email = #{userEmail} and user_city = #{userCity}
登录后复制

choose

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

<select id="findByUser" resultType="com.example.mybatis.entity.User">
        select
        id, username, user_email userEmail, user_city userCity, age
        from user        <where>
            <choose>
                <when test="username != null and username != &#39;&#39;">
                    username = #{username}                </when>
                <when test="userEmail != null and userEmail != &#39;&#39;">
                    and user_email = #{userEmail}                </when>
                <when test="userCity != null and userCity != &#39;&#39;">
                    and user_city = #{userCity}                </when>
            </choose>
        </where>
    </select>
登录后复制

set

set 标签用于 Update 操作,会自动根据参数选择生成 SQL 语句。

接口定义如下

public int updateUser(User user);
登录后复制

接口对应的 Mapper.xml 定义如下所示

<update id="updateUser" parameterType="com.example.mybatis.entity.User">
       update user       <set>
           <if test="username != null and username != &#39;&#39;">
               username=#{username},           </if>
           <if test="userEmail != null and userEmail != &#39;&#39;">
               user_email=#{userEmail},           </if>
           <if test="userCity != null and userCity != &#39;&#39;">
               user_city=#{userCity},           </if>
           <if test="age != null">
              age=#{age}           </if>
       </set>
       where id=#{id}    </update>
登录后复制

foreach

foreach 标签可以迭代生成一系列值

*用于 SQL 的 in 语句 *

接口定义如下所示

public List<User> getUsersByIds(List<Integer> ids);
登录后复制

接口对应的 Mapper.xml 定义如下所示

<!--
        collection: 指定要遍历的集合
            默认情况下
                如果为Collection类型的,key为collection;
                如果为List类型的,key为list
                如果是数组类型,key为array
            可以通过@Param("ids")来指定key
        item: 将当前遍历的元素赋值给指定的变量
        open: 给遍历的结果添加一个开始字符
        close: 给遍历的结果添加一个结束字符
        separator: 每个元素之间的分隔符
    --><select id="getUsersByIds"
        resultType="com.example.mybatis.entity.User">
    select * from user
    where id in    <foreach collection="list" item="id" open="(" close=")" separator=",">
        #{id}    </foreach></select>
登录后复制

用于批量插入

接口定义如下所示

public int addUserList(List<User> users);
登录后复制

接口对应的 Mapper.xml 定义如下所示

<insert id="addUserList"
        parameterType="com.example.mybatis.entity.User">
    insert into user
    (username, user_email, user_city, age)
    values    <foreach item="user"  collection="list" separator=",">
        (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age})    </foreach></insert><!--返回自增主键--><insert id="addUserList"
        parameterType="com.example.mybatis.entity.User"
        useGeneratedKeys="true"
        keyProperty="id">
    insert into user
    (username, user_email, user_city, age)
    values    <foreach item="user"  collection="list" separator=",">
        (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age})    </foreach></insert><!--还可以这样写--><!--
    这种方式需要数据库连接属性设置allowMultiQueries=true
    这种分号分隔多个SQL还可以用于其他的批量操作,如修改、删除
--><insert id="addUserList"
        parameterType="com.example.mybatis.entity.User">
    <foreach item="user"  collection="list" separator=";">
        insert into user
        (username, user_email, user_city, age)
        values
        (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age})    </foreach></insert><!--如果是Oracle数据库,则需要这样写--><insert id="addUserList"
        parameterType="com.example.mybatis.entity.User">
    <foreach item="user" open="begin" close="end;"  collection="list">
        insert into user
        (username, user_email, user_city, age)
        values
        (#{user.username}, #{user.userEmail}, #{user.userCity}, #{user.age});    </foreach></insert>
登录后复制

以上是学习MyBatis 动态 SQL的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

Hibernate 框架中 HQL 和 SQL 的区别是什么? Hibernate 框架中 HQL 和 SQL 的区别是什么? Apr 17, 2024 pm 02:57 PM

HQL和SQL在Hibernate框架中进行比较:HQL(1.面向对象语法,2.数据库无关的查询,3.类型安全),而SQL直接操作数据库(1.与数据库无关的标准,2.可执行复杂查询和数据操作)。

Oracle SQL中除法运算的用法 Oracle SQL中除法运算的用法 Mar 10, 2024 pm 03:06 PM

《OracleSQL中除法运算的用法》在OracleSQL中,除法运算是常见的数学运算之一。在数据查询和处理过程中,除法运算可以帮助我们计算字段之间的比例或者得出特定数值的逻辑关系。本文将介绍OracleSQL中除法运算的用法,并提供具体的代码示例。一、OracleSQL中除法运算的两种方式在OracleSQL中,除法运算可以使用两种不同的方式进行

Oracle和DB2的SQL语法比较与区别 Oracle和DB2的SQL语法比较与区别 Mar 11, 2024 pm 12:09 PM

Oracle和DB2是两个常用的关系型数据库管理系统,它们都有自己独特的SQL语法和特点。本文将针对Oracle和DB2的SQL语法进行比较与区别,并提供具体的代码示例。数据库连接在Oracle中,使用以下语句连接数据库:CONNECTusername/password@database而在DB2中,连接数据库的语句如下:CONNECTTOdataba

详解MyBatis动态SQL标签中的Set标签功能 详解MyBatis动态SQL标签中的Set标签功能 Feb 26, 2024 pm 07:48 PM

MyBatis动态SQL标签解读:Set标签用法详解MyBatis是一个优秀的持久层框架,它提供了丰富的动态SQL标签,可以灵活地构建数据库操作语句。其中,Set标签是用于生成UPDATE语句中SET子句的标签,在更新操作中非常常用。本文将详细解读MyBatis中Set标签的用法,以及通过具体的代码示例来演示其功能。什么是Set标签Set标签用于MyBati

SQL出现5120错误怎么解决 SQL出现5120错误怎么解决 Mar 06, 2024 pm 04:33 PM

解决办法:1、检查登录用户是否具有足够的权限来访问或操作该数据库,确保该用户具有正确的权限;2、检查SQL Server服务的帐户是否具有访问指定文件或文件夹的权限,确保该帐户具有足够的权限来读取和写入该文件或文件夹;3、检查指定的数据库文件是否已被其他进程打开或锁定,尝试关闭或释放该文件,并重新运行查询;4、尝试以管理员身份运行Management Studio等等。

数据库技术大比拼:Oracle和SQL的区别有哪些? 数据库技术大比拼:Oracle和SQL的区别有哪些? Mar 09, 2024 am 08:30 AM

数据库技术大比拼:Oracle和SQL的区别有哪些?在数据库领域中,Oracle和SQLServer是两种备受推崇的关系型数据库管理系统。尽管它们都属于关系型数据库的范畴,但两者之间存在着诸多不同之处。在本文中,我们将深入探讨Oracle和SQLServer之间的区别,以及它们在实际应用中的特点和优势。首先,Oracle和SQLServer在语法方面存

MyBatis 一级缓存详解:如何提升数据访问效率? MyBatis 一级缓存详解:如何提升数据访问效率? Feb 23, 2024 pm 08:13 PM

MyBatis一级缓存详解:如何提升数据访问效率?在开发过程中,高效的数据访问一直是程序员们关注的焦点之一。而对于MyBatis这样的持久层框架而言,缓存是提升数据访问效率的关键方法之一。MyBatis提供了一级缓存和二级缓存两种缓存机制,其中一级缓存是默认开启的。本文将详细介绍MyBatis一级缓存的机制,并提供具体的代码示例,帮助读者更好地理

解析MyBatis的缓存机制:比较一级缓存和二级缓存的特点和用法 解析MyBatis的缓存机制:比较一级缓存和二级缓存的特点和用法 Feb 25, 2024 pm 12:30 PM

MyBatis的缓存机制解析:一级缓存与二级缓存的区别与应用在MyBatis框架中,缓存是一个非常重要的特性,可以有效提升数据库操作的性能。其中,一级缓存和二级缓存是MyBatis中常用的两种缓存机制。本文将详细解析一级缓存与二级缓存的区别与应用,并提供具体的代码示例进行说明。一、一级缓存一级缓存也被称为本地缓存,它默认开启且不可关闭。一级缓存是SqlSes

See all articles