MyBatis动态SQL的示例

77次阅读
没有评论

共计 6331 个字符,预计需要花费 16 分钟才能阅读完成。

自动写代码机器人,免费开通

这篇文章将为大家详细讲解有关 MyBatis 动态 SQL 的示例,丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

动态 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 !=  
 username = #{username}  /if 
  if test= userEmail != null and userEmail !=  
 and user_email = #{userEmail}  /if 
  if test= userCity != null and userCity !=  
 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 !=  
 username = #{username}
  /if 
  if test= userEmail != null and userEmail !=  
 and user_email = #{userEmail}
  /if 
  if test= userCity != null and userCity !=  
 and user_city = #{userCity}
  /if 
  /where 
  /select

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

trim

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

如果语句的前面或后面遇到 prefixOverrides 或 suffixOverrides 属性中指定的值,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 !=  
 username = #{username}  /if 
  if test= userEmail != null and userEmail !=  
 and user_email = #{userEmail}  /if 
  if test= userCity != null and userCity !=  
 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 !=  
 username = #{username}  /when 
  when test= userEmail != null and userEmail !=  
 and user_email = #{userEmail}  /when 
  when test= userCity != null and userCity !=  
 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 !=  
 username=#{username},  /if 
  if test= userEmail != null and userEmail !=  
 user_email=#{userEmail},  /if 
  if test= userCity != null and userCity !=  
 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 的示例就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

向 AI 问一下细节

丸趣 TV 网 – 提供最优质的资源集合!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-16发表,共计6331字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)