> 文章列表 > MyBatis 动态SQL

MyBatis 动态SQL

MyBatis 动态SQL

MyBatis 的强大特性之一便是它的动态 SQL。通常使用动态 SQL 不可能是独立的一部分,MyBatis 当然使用一种强大的动态 SQL 语言来改进这种情形,这种语言可以被用在任意的 SQL 映射语句中。MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

常用元素

元素 说明 备注
if 判断语句,用于单条件判断 满足条件时,if标签才会链接 案例
choose(when,otherwise) 相当于switch…case…default语句 有时候用不到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用choose标签可以满足 案例
where SQL中的where条件判断 它所包含标签中有返回值的话,它就会插入一个where,如果标签返回内容是以AND或OR开头的话,则它会剔除掉 案例
trim 去除多余的关键字 无内容时不起作用,可以在标签内容前面/后面添加或删除指定内容 案例
set SQL语句的动态更新 在至少有一个子元素返回了SQL语句时,才会向SQL语句中添加SET,并且如果SET之后是以,开头的话,会自动将其删掉 案例
foreach 循环语句,常用于in语句等列举条件中 对集合进行遍历 案例

SQL片段:有时候可以通过将部分代码抽出来作为公用,使用时候可以直接调用

OGNL

OGNL的全称是Object-Graph Navigation Language,即对象图导航语言,它是一种功能强大的开源表达式语言。使用这种表达式语言可以通过某种表达式语法存取Java对象的任意属性,调用Java对象的方法,以及实现类型转行等。
OGNL的操作实际上是围绕OGNL结构的三个要素进行的,分别是表达式(expression)、上下文对象(context)和根对象(root)。

1.表达式

表达式是整个OGNL的核心,OGNL会根据表达式到对象中取值。所有OGNL操作都是针对表达式解析后进行的,它表明了此次OGNL操作要“做什么”。实际上,表达式就是一个带有语法含义的字符串,这个字符串规定了操作的类型和操作的内容。

2.上下文对象

上下文对象规定了OGNL操作“在哪里进行”。context对象是一个Map类型的对象,在表达式中访问context中的对象,需要使用#号加对象名称,即“#对象名称”的形式。例如要获取context对象中user对象的username值,可以如下书写:

#user.username

3.根对象

根对象可以理解为OGNL的操作对象,OGNL可以对根对象进行取值或写值等操作,表达式规定了“做什么”,而根对象则规定了“对谁操作”。实际上根对象所在的环境就是OGNL的上下文对象环境。

OGNL在java环境的运用

引入OGNLjar包

<!-- https://mvnrepository.com/artifact/ognl/ognl --><dependency><groupId>ognl</groupId><artifactId>ognl</artifactId><version>3.1.12</version></dependency>
package com.example.test;import com.example.pojo.User;
import ognl.Ognl;
import ognl.OgnlContext;
import ognl.OgnlException;
import org.junit.Test;/* ClassName: TestOGNL* Package: com.example.test* Description: @Create 2023/4/5 20:57* @Version 1.0*/
public class TestOGNL {/* OGNL调用对象的方法*/@Testpublic void testOGNLInvokedObjectMethod() {try {//创建context对象OgnlContext context = new OgnlContext();//利用context来获取root对象Object root = context.getRoot();//Ognl中的静态方法getValue(expression, context, root, resultType)可以用来获取数据Object value = Ognl.getValue("'helloworld'.length()", context, root);//expression就是方法表达式System.out.println(value.toString());} catch (OgnlException e) {e.printStackTrace();}}/* 利用ognl访问类中的静态方法*/@Testpublic void testOGLNStaticMethod() {try {//创建context对象OgnlContext context = new OgnlContext();//利用context来获取root对象Object root = context.getRoot();//Ognl中的静态方法getValue(expression, context, root, resultType)可以用来获取数据Object value = Ognl.getValue("@java.lang.Math@random()", context, root);//这里注意获取静态方法表达式是固定表达: @类名@方法名System.out.println(value.toString());} catch (OgnlException e) {e.printStackTrace();}}/* 访问root区中的数据*/@Testpublic void testOGNLGetDataFromRoot(){//创建context对象OgnlContext context = new OgnlContext();//注意,这里不能在getValue方法外面初始化获取root对象,不然导致该root为null,传进方法里面,由于root在外面已经被定义,方法底层就不会帮助创建赋值,直接报异常,name值根本不会再存Object root = context.getRoot();System.out.println(root);//向root区域存值,setRoot(Object obj),root就是通过一个对象找到与它关联的对象,所以只能用来存对象类型TempUser user = new TempUser();user.setName("Lily");context.setRoot(user);//root的取值不需要加上#,它是ognl内部的,所以不需要加#来特意告诉ognlString value;try {value = (String) Ognl.getValue("name", context, context.getRoot());System.out.println(value);} catch (OgnlException e) {// TODO Auto-generated catch blocke.printStackTrace();}}/* 获取context区域的值*/@Testpublic void testGetVauleFromContext(){//创建context对象OgnlContext context = new OgnlContext();//利用context来获取root对象Object root = context.getRoot();//向context区域存值,set一般向里面存对象,而context区域用put是存值context.put("name","Lily");String value;try {//root的取值不需要加上#,它是ognl内部的,所以不需要加#来特意告诉ognl,而context区域上该ognl的所处的上下文环境,外部,要加上#说明value = (String) Ognl.getValue("#name", context, root);System.out.println(value);} catch (OgnlException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
class TempUser{private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "TempUser{" +"name='" + name + '\\'' +'}';}
}

零食排行榜