java when for where_MyBatis-动态SQL的if、choose、when、otherwise、trim、where、set、foreach使用(各种标签详解), 以及实体间关系...

比较全的文档:https://www.cnblogs.com/zhizhao/p/7808880.html 或 https://blog.csdn.net/zhll3377/article/details/8203440

四:常用的动态语句标签:通过动态sql标签可以进行条件判断,条件遍历等操作从而满足结果的需要

0. 

select* from t_blog where 1 = 1

and title=#{title}

and content=#{content}

and owner=#{owner}

SELECT*from STUDENT_TBL STWHERE ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')

select* from emp where 1 = 1

and job=#{job}

and deptno=#{deptno}

1.  : 使用其可以代替sql语句中的where关键字,一般防止在条件查询的最外层

2.:常用于更新语句中,替代 sql中的“set”关键字,特别是在联合进行判断是,可以有效方式当某个参数为空或者不合法是错误的更新到数据库中

update orderitem

product_id= #{productId,jdbcType=VARCHAR},

count= #{count,jdbcType=INTEGER},

where orderitem_id= #{orderitemId,jdbcType=VARCHAR}

3.  标签组:也是一个用于条件判断的标签组,和的不同之处在于条件从进入,去匹配中的添加,一旦匹配马上结束;若到找不到匹配项,将执行中的语句;可以理解为是 && 关系 是 || 关系

SELECT*from STUDENT_TBL ST

ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')

AND ST.STUDENT_SEX=#{studentSex}

AND ST.STUDENT_BIRTHDAY=#{studentBirthday}

AND ST.CLASS_ID=#{classEntity.classID}

3.1. :

有时候我们并不想应用所有的条件,而只是想从多个选项中选择一个。MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。  if是与(and)的关系,而choose是或(or)的关系。

5.

当在update语句中使用if标签时,如果前面的if没有执行,则或导致逗号多余错误。使用set标签可以将动态的配置SET 关键字,和剔除追加到条件末尾的任何不相关的逗号。

没有使用if标签时,如果有一个参数为null,都会导致错误,如下示例:

UPDATE STUDENT_TBL

SET STUDENT_TBL.STUDENT_NAME=#{studentName},

STUDENT_TBL.STUDENT_SEX=#{studentSex},

STUDENT_TBL.STUDENT_BIRTHDAY=#{studentBirthday},

STUDENT_TBL.CLASS_ID=#{classEntity.classID}

WHERE STUDENT_TBL.STUDENT_ID=#{studentID};

6.标签:

update username=#{name} ,gender=#{gender} ,

1>.

prefix:在trim标签内sql语句加上前缀。

suffix:在trim标签内sql语句加上后缀。

suffixOverrides:指定去除多余的后缀内容,如:suffixOverrides=",",去除trim标签内sql语句多余的后缀","。

prefixOverrides:指定去除多余的前缀内容

下面是一个往购物车表中插入数据的mybatis语句

insert into cart (把 尾部的,替换成 ")")

id,

user_id,

deal_id,

deal_sku_id,

count,

create_time,

update_time,

#{id,jdbcType=BIGINT},

#{userId,jdbcType=BIGINT},

#{dealId,jdbcType=BIGINT},

#{dealSkuId,jdbcType=BIGINT},

#{count,jdbcType=INTEGER},

#{createTime,jdbcType=TIMESTAMP},

#{updateTime,jdbcType=TIMESTAMP},

假设没有指定 suffixOverrides="," ,

执行的sql语句也许是这样的:insert into cart (id,user_id,deal_id,) values(1,2,1,);显然是错误的

指定之后语句就会变成            insert into cart (id,user_id,deal_id) values(1,2,1);这样就将“,”去掉了。

前缀也是一个道理这里就不说了。

来自: https://blog.csdn.net/qq_33054511/article/details/70490046

d05b6b365b6af2a4edf734016793038a.png

o(^▽^)o可以看到成功匹配掉了开头的$和末尾的*

String[] deptnos = {"10", "20", "30"};

List empList = sqlSession.getMapper(EmpMapper.class).getEmpByArray(deptnos);

2>.

trim是更灵活的去处多余关键字的标签,他可以实践where和set的效果。 where例子的等效trim语句:

SELECT*from STUDENT_TBL ST (头部的and或or 都替换成"where")

ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')

AND ST.STUDENT_SEX=#{studentSex}

AND ST.position like #{position}

【解释】

a.我们使用替代标签。

b.属性“prefix”表示:加入前缀where

c.属性“prefixOverrides”表示:自动覆盖第一个“and”或者“or”

d.后缀的用法类似;

set例子的等效trim语句(是一个非常强大的标签,因此,我们也可以通过来实现的功能,如下:【这种写法的运行效果与等价】):

UPDATE STUDENT_TBL

STUDENT_TBL.STUDENT_NAME=#{studentName},

STUDENT_TBL.STUDENT_SEX=#{studentSex},

STUDENT_TBL.STUDENT_BIRTHDAY=#{studentBirthday},

STUDENT_TBL.CLASS_ID=#{classEntity.classID}

WHERE STUDENT_TBL.STUDENT_ID=#{studentID};

7.标签:该标签的作用是遍历集合类型的条件

属性:collection=“array” / collection = “list”  ----->是数组类型,还是集合类型

item=“ productId ”------> 参数名

open="(" separator="," close=")"  ------>开始符号,分隔符号,结束符号

index=“ ” ---->结束下标位置,不配置该参数时,默认为全部遍历

delete from product where product_Id in

#{productId,jdbcType = VARCHAR}

3.4.  参数为Array实例的写法:

SELECT*FROM STUDENT_TBL ST

WHERE ST.CLASS_ID IN#{ids}

接口的方法声明:

public List getStudentListByClassIDs(String[] ids);

public List getStudentListByClassIDs(String[] ids);测试代码,查询学生中,在20000002、20000003这两个班级的学生:

3.5. Map类型的参数

select * from t_user where username like '%${username}%' and id in

#{item}

public List dynamicForeach3Test(Map params);

五、(https://blog.csdn.net/qq_29233973/article/details/51433924 + https://blog.csdn.net/zenson_g/article/details/10137665)

1. 引用:通过标签引用,refid="" 中的值指向需要引用的中的id=“”属性

o.order_id,o.cid,o.address,o.create_date,o.orderitem_id,i.orderitem_id,i.product_id,i.count

select

from ordertable o

join orderitem i on o.orderitem_id = i.orderitem_id

where o.order_id = #{orderId}

2. 映射管理器resultMap:映射管理器,是Mybatis中最强大的工具,使用其可以进行实体类之间的关系,并管理结果和实体类间的映射关系:

1)一对一关系   property = “ ” 被维护实体在宿主实体中的属性名,javaType = " " 被维护实体的类型

package pojo;

public class Orderitem {

private String orderitemId;

private String productId;

private Integer count;

private Product product;

从上方代码段可以看出:Product 对象在 Orderitem 实体中以 product 属性存在

Orderitemmapper.xml

通过xml的配置可以看出,在resultMap映射管理器中,通过 进行了维护,也就是在查询Orderitem对象时,可以把关联的Product对象的信息也查询出来

2)一对多关系的维护 property = “ ” 被维护实体在宿主实体中的属性名 ,ofType=“ ”是被维护方在宿主类中集合泛型限定类型

【由于在一对多关系中,多的一放是以List形式存在,因此ofType的值取用Lsit> 的泛型对象类型】

public class OrderTable {

private String orderId;

private String cid;

private String address;

private Date createDate;

private String orderitemId;

private List orderitemList ;

}

OrderTableMapper.xml:

3)在resultMap 中需要注意两点:

3.1)关联关系的维护可以根据实体类之间的实际情况进行嵌套维护

实例:

我们又一次联合了博客表和文章表,而且关注于保证特性,结果列标签的简单映射。现在用文章映射集合映射博客,可以简单写为:

同样,要记得 id 元素的重要性,如果你不记得了,请阅读上面的关联部分。

同样, 如果你引用更长的形式允许你的结果映射的更多重用, 你可以使用下面这个替代的映射:

注意 这个对你所映射的内容没有深度,广度或关联和集合相联合的限制。当映射它们时你应该在大脑中保留它们的表现。你的应用在找到最佳方法前要一直进行的单元测试和性能测试。好在 myBatis 让你后来可以改变想法,而不对你的代码造成很小(或任何)影响。

高级关联和集合映射是一个深度的主题。文档只能给你介绍到这了。加上一点联系,你会很快清楚它们的用法。

3.2)关于出现重复列名的处理:在实际操作过程中,查询到的结果可能会出现相同的列名,这样会对映射到实体属性带来影响甚至出现报错,那么对待这个问题可以通过对列取别名的方式处理:

要记住类型别名是你的伙伴。使用它们你可以不用输入类的全路径。比如:

select id, username, hashedPassword

from some_table

where id=#{id}

这些情况下,MyBatis 会在幕后自动创建一个 ResultMap,基于属性名来映射列到 JavaBean 的属性上。如果列名没有精确匹配,你可以在列名上使用 select 字句的别名(一个基本的 SQL 特性)来匹配标签。比如:

select

user_id as"id",

user_name as"userName",

hashed_password as"hashedPassword"from some_table

where id=#{id}

ResultMap 最优秀的地方你已经了解了很多了,但是你还没有真正的看到一个。这些简单的示例不需要比你看到的更多东西。只是出于示例的原因, 让我们来看看最后一个示例中外部的 resultMap 是什么样子的,这也是解决列名不匹配的另外一种方式。

引用它的语句使用 resultMap 属性就行了(注意我们去掉了 resultType 属性)。比如:

3.3)鉴别器:

有时一个单独的数据库查询也许返回很多不同 (但是希望有些关联) 数据类型的结果集。鉴别器元素就是被设计来处理这个情况的, 还有包括类的继承层次结构。鉴别器非常容易理解,因为它的表现很像 Java 语言中的 switch 语句。

定义鉴别器指定了 column 和 javaType 属性。列是 MyBatis 查找比较值的地方。 JavaType 是需要被用来保证等价测试的合适类型(尽管字符串在很多情形下都会有用)

比如,我们如何映射下面这个语句?

select

B.id as blog_id,

B.title as blog_title,

B.author_id as blog_author_id,

A.id as author_id,

A.username as author_username,

A.password as author_password,

A.email as author_email,

A.bio as author_bio,

A.favourite_section as author_favourite_section,

P.id as post_id,

P.blog_id as post_blog_id,

P.author_id as post_author_id,

P.created_on as post_created_on,

P.section as post_section,

P.subject as post_subject,

P.draft as draft,

P.body as post_body,

C.id as comment_id,

C.post_id as comment_post_id,

C.name as comment_name,

C.comment as comment_text,

T.id as tag_id,

T.name as tag_name

from Blog B

left outer join Author A on B.author_id=A.id

left outer join Post P on B.id=P.blog_id

left outer join Comment C on P.id=C.post_id

left outer join Post_Tag PT on PT.post_id=P.id

left outer join Tag T on PT.tag_id=T.id

where B.id= #{id}

下面是一个完整的复杂结果映射例子 (假设作者, 博客, 博文, 评论和标签都是类型的别名) 我们来看看, 。但是不用紧张, 我们会一步一步来说明。当天最初它看起来令人生畏,但实际上非常简单。

(对应实体中的 有参构造函数)

(association 专门负责描述一对一的关系)

(鉴别器:switch)

resultMap :

constructor - 类在实例化时,用来注入结果到构造方法中id – 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能

idArg - ID 参数;标记结果作为 ID 可以帮助提高整体效能

arg - 注入到构造方法的一个普通结果

result – 注入到字段或 JavaBean 属性的普通结果

association – 一个复杂的类型关联;许多结果将包成这种类型

嵌入结果映射 – 结果映射自身的关联,或者参考一个

collection – 复杂类型的集

嵌入结果映射 – 结果映射自身的集,或者参考一个

discriminator – 使用结果值来决定使用哪个结果映射

case – 基于某些值的结果映射

嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相 同的元素,或者它可以参照一个外部的结果映射。

最佳实践 通常逐步建立结果映射。单元测试的真正帮助在这里。如果你尝试创建一次创建一个向上面示例那样的巨大的结果映射, 那么可能会有错误而且很难去控制它来工作。开始简单一些,一步一步的发展。而且要进行单元测试!使用该框架的缺点是它们有时是黑盒(是否可见源代码) 。你确定你实现想要的行为的最好选择是编写单元测试。它也可以你帮助得到提交时的错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值