mysql的trim动态标签_Mybatis之trim标签的理解

转自:https://www.cnblogs.com/westward/p/6706570.html

最近在学Mybatis,在学到动态sql的trim标签时,很迷惑。不知所以然。看别人的博客和论坛里的解释,太宽泛,还是不能理解:

trim元素的主要功能是可以在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix;可以把包含内容的首部某些内容覆盖,即忽略,也可以把尾部的某些内容覆盖,对应的属性是prefixOverrides和suffixOverrides;正因为trim有这样的功能,所以我们也可以非常简单的利用trim来代替where元素的功能。

例1:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1

2 select * from users

3

4

5 name=#{name}

6

7

8 and address=#{address}

9

10

11

48304ba5e6f9fe08f3fa1abda7d326ab.png

可以看到后台打印的sql:

c7c84d755dbd21487838cb5f7b53ef41.png

例2:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1

2 select * from users

3

4

5 or name=#{name}

6

7

8 and address=#{address}

9

10

11

48304ba5e6f9fe08f3fa1abda7d326ab.png

后台报错:

fb74318d8154f2ff4e963a833c1c74bb.png

怎么办呢?遇到问题,当然要想办法解决。灵光一闪,我不是把源代码绑定到了mybatis的jar上了吗?对,那就看源代码,源代码还能debug呢,更方便。

trim标签的java方法调用栈轨迹:(只写出关键的几个)

org.apache.ibatis.scripting.xmltags.TrimSqlNode.apply()

org.apache.ibatis.scripting.xmltags.TrimSqlNode.FilteredDynamicContext.applyAll()

org.apache.ibatis.scripting.xmltags.TrimSqlNode.FilteredDynamicContext.applyPrefix()

applyPrefix()的源代码:

代码块1:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 private void applyPrefix(StringBuilder sql, String trimmedUppercaseSql) {

2 if (!prefixApplied) {

3 prefixApplied = true;

4 if (prefixesToOverride != null) {

5 for (String toRemove : prefixesToOverride) {

6 if (trimmedUppercaseSql.startsWith(toRemove)) {

7 sql.delete(0, toRemove.trim().length());

8 break;

9 }

10 }

11 }

12 if (prefix != null) {

13 sql.insert(0, " ");

14 sql.insert(0, prefix);

15 }

16 }

17 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

prefixApplied的值:初始是false.从下面代码内部类TrimSqlNode.FilteredDynamicContext的构造器可以看出:

代码块2:

48304ba5e6f9fe08f3fa1abda7d326ab.png

1 public FilteredDynamicContext(DynamicContext delegate) {

2 super(configuration, null);

3 this.delegate = delegate;

4 this.prefixApplied = false;

5 this.suffixApplied = false;

6 this.sqlBuffer = new StringBuilder();

7 }

48304ba5e6f9fe08f3fa1abda7d326ab.png

List集合类型prefixesToOverride :trim标签的属性prefixOverrides,

String类型prefix:trim标签的属性prefix.

trimmedUppercaseSql:trim标签的子标签里的sql语句.

见下面代码:(TrimSqlNode的成员变量):

代码块3:

1 private String prefix;

2 private String suffix;

3 private List prefixesToOverride;

4 private List suffixesToOverride;

现在我们在回看代码块1,会发现整个方法的大致意思:当trim标签prefixOverrides属性不为空时,遍历prefixOverrides集合的值,并且用trim标签里第一个子标签(比如if标签)的sql的语句头去匹配prefixOverrides集合的元素值,一旦匹配成功,则将第一个子标签的sql语句匹配的元素删掉,继续向下运行,判断prefix属性是否有值,若有值,在将prefix的值放到第一个子标签的sql语句开头。

所以,例2,将prefixOverrides的值改为 or  或者 and|or 就行了。

好吧,就是这样,可能是自己的语言表达能力不够水平,感觉还是看代码来的精确 :)

最后在总结下吧:

trim标签的prefixOverrides和prefix分两步骤:

1.如果prefixOverrides有元素,拿元素去匹配 第一个子标签sql语句,若匹配上,就删掉sql语句的匹配部分,跳到2

2.如果prefix有值,就在  第一个子标签sql语句 的最前面加上 prefix的值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值