java指导Mybatis动态Sql处理解析
2023-02-27 金融
for (int i = 0; i
XNode child = node.newXNode(children.item(i));
//辨别侄类型或表征中不会的自然语言概要 || 侄类型元数据中不会的 CDATA 部(不不会由解器解的自然语言)
if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
String data = child.getStringBody("");
//解data
TextSqlNode textSqlNode = new TextSqlNode(data);
//辨别局限性的Sql原作者是否为快照原作者
if (textSqlNode.isDynamic()) {
contents.add(textSqlNode);
isDynamic = true;
} else {
contents.add(new StaticTextSqlNode(data));
}
//如果侄类型为代表类型,则无需解侄类型
} else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628
//换取类型的名字
String nodeName = child.getNode().getNodeName();
//根据类型名换取到类型链表的处理操作过程器,Mybatis备有了8中不会类型处理操作过程器,ChooseHandler、IfHandler、OtherwiseHandler
//TrimHandler、BindHandler、WhereHandler、SetHandler、ForEachHandler。博文不会给大家统计分析下IfHandler
NodeHandler handler = nodeHandlerMap.get(nodeName);
if (handler == null) {
throw new BuilderException("Unknown element in SQL statement.");
}
//函数调至用近似于的handler同步进行链表处理操作过程,运算符函数调至用就在这块
handler.handleNode(child, contents);
isDynamic = true;
}
}
//创建MixedSqlNode
return new MixedSqlNode(contents);
}
// 上头我们看下IfHandler是如何处理操作过程,IfHandler是XMLScriptBuilder的内部类
private class IfHandler implements NodeHandler {
public IfHandler() {
// Prevent Synthetic Access
}
//我们着重统计分析这个原理
@Override
public void handleNode(XNode nodeToHandle, List targetContents) {
//函数调至用parseDynamicTags同步进行链表解。这里就是运算符,又函数调至用了上头的原理。
MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
//换取if近似于的赋值
String test = nodeToHandle.getStringAttribute("test");
//创建IfSqlNode
IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test);
targetContents.add(ifSqlNode);
}
}
上头我们根据Sql原作者和指派结果来统计分析。
// 快照Sql原作者和链表的快照Sql原作者
select * from user where id> #{ user.id}
AND name = #{ user.name}
AND name = #{ user.name}
AND name = #{ user.name}
上头我们统计分析下指派结果:
上头运算符结果已经用不通颜色上面了,大家自己看下。特别无需看下IfSqlNode的表征。
快照Sql解
快照Sql解主要是指派数据库操作的时候把快照Sql转换再加JDBC能辨认的Sql原作者。【关注尚硅谷,得心应手学IT】Mybatis中不会主要是通过SqlSource来解Sql原作者,替换再加JDBC能辨认的Sql原作者。我们先看下类图。
SqlSource:备有了Sql解的不道德。
RawSqlSource:快照Sql原作者的编译,只生再加一次StaticSqlSource。
DynamicSqlSource:每次函数调至用都不会生再加StaticSqlSource。每次函数调至用传入模板意味著不一样。无需每次生再加StaticSqlSource。
ProviderSqlSource:第三方原作者语法的集再加。
FreeMarkerSqlSource:对FreeMarker的赞成。
StaticSqlSource:StaticSqlSource只是对上头4中不会类别认真了层PCB。博文从未这个类不会更加宁静些。
我们这次主要对StaticSqlSource、RawSqlSource、和DynamicSqlSource同步进行统计分析。
StaticSqlSource
毕竟StaticSqlSource就是对其他几种类别Sql处理操作过程器结果同步进行纸盒。我们看下GCC。
//我们主要统计分析下getBoundSql
public class StaticSqlSource implements SqlSource {
private final String sql;
private final List parameterMappings;
private final Configuration configuration;
public StaticSqlSource(Configuration configuration, String sql) {
this(configuration, sql, null);
}
public StaticSqlSource(Configuration configuration, String sql, List parameterMappings) {
this.sql = sql;
this.parameterMappings = parameterMappings;
this.configuration = configuration;
}
//getBoundSql就是创建一个BoundSql实例。
@Override
public BoundSql getBoundSql(Object parameterObject) {
return new BoundSql(configuration, sql, parameterMappings, parameterObject);
}
}
看放是不是非常恰当,毕竟有些编码确实从未我们想象中不会那么自知。
RawSqlSource
// 我们着重统计分析RawSqlSource原理
public class RawSqlSource implements SqlSource {
private final SqlSource sqlSource;
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class parameterType) {
this(configuration, getSql(configuration, rootSqlNode), parameterType);
}
//这里意味着了对快照原作者的解,乃是的快照原作者解就是把 #{}解再加?快照Sql解是在解Mapper.xml的时候指派的
public RawSqlSource(Configuration configuration, String sql, Class parameterType) {
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class clazz = parameterType == null ? Object.class : parameterType;
//通过函数调至用SqlSourceBuilder的parse原理来解Sql
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap());
}
private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
DynamicContext context = new DynamicContext(configuration, null);
rootSqlNode.apply(context);
return context.getSql();
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
return sqlSource.getBoundSql(parameterObject);
}
}
上头我们来看下SqlSourceBuilder的parse原理
public SqlSource parse(String originalSql, Class parameterType, Map additionalParameters) {
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
//寻觅Sql原作者中不会#{}上面的原作者用?号同步进行替代。GenericTokenParser里头编码来得复杂,博文也从未分析。
//很感兴趣自己可以分析下。
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
String sql = parser.parse(originalSql);
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}
DynamicSqlSource
快照Sql解主要由DynamicSqlSource来放再加。这里头又是通过运算符调至同步进行sql解。我们还是依循上头的Sql给大家说什么解。
public class DynamicSqlSource implements SqlSource {
private final Configuration configuration;
private final SqlNode rootSqlNode;
public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {
this.configuration = configuration;
this.rootSqlNode = rootSqlNode;
}
@Override
public BoundSql getBoundSql(Object parameterObject) {
//快照Sql解表达式
DynamicContext context = new DynamicContext(configuration, parameterObject);
//rootSqlNode就是我们前面说什么解的,把快照Sql解再加SqlNode实例。表面为MixedSqlNode链表,链表唯储了
//链表下的所有侄链表。里头运算符函数调至用并根据传入模板的表征核对是否无需拼南和sql
rootSqlNode.apply(context);
//这块编码和上头快照Sql南和编码相反。
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class parameterType = parameterObject == null ? Object.class : parameterObject.getClass();
//把我们快照Sql中不会的#{}替换再加?
SqlSource sqlSource = sqlSourceParser.parse(context.getSql(), parameterType, context.getBindings());
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
for (Map.Entry entry : context.getBindings().entrySet()) {
boundSql.setAdditionalParameter(entry.getKey(), entry.getValue());
}
return boundSql;
}
}
快照Sql解apply原理博文只根据场景介绍下MixedSqlNode和IfSqlNode的apply原理。其他很感兴趣自己去分析下。逻辑大体相反,意味着有些区别。
public class MixedSqlNode implements SqlNode {
private final List contents;
public MixedSqlNode(List contents) {
this.contents = contents;
}
//换取循环系统SqlNode沙罗的所有SqlNode,函数调至用apply原理根据传入模板和必需同步进行快照sql的拼南和。
//沙罗中不会的SqlNode意味著是一个恰当的SqlNode实例,也意味著是一个MixedSqlNode或者有更加多的链表。
//博文的例证就是3个链表If查询。根据博文的Sql原作者,这里实际上不会函数调至用IfSqlNode的apply原理。
//我们南和下来看下IfSqlNode是如何意味着的。
@Override
public boolean apply(DynamicContext context) {
for (SqlNode sqlNode : contents) {
sqlNode.apply(context);
}
return true;
}
}
IfSqlNode的apply
public class IfSqlNode implements SqlNode {
//ExpressionEvaluator不会函数调至用ognl来对赋值同步进行解
private final ExpressionEvaluator evaluator;
private final String test;
private final SqlNode contents;
public IfSqlNode(SqlNode contents, String test) {
this.test = test;
this.contents = contents;
this.evaluator = new ExpressionEvaluator();
}
@Override
public boolean apply(DynamicContext context) {
//context.getBindings()里头就唯储这立即模板,这里是一个HashMap,OGNl里头编码博文从未分析。
//如果必需if再加立,实际上换取contents中不会的SqlNode的apply原理同步进行快照原作者处理操作过程。
if (evaluator.evaluateBoolean(test, context.getBindings())) {
contents.apply(context);
return true;
}
return false;
}
}
这块编码很多运算符函数调至用,博文自认为说什么的不实在太透彻,所以大家看放务必自己去调至试下。
归纳
Mybatis快照Sql从解到指派分为2个操作过程上头对这个2个操作过程同步进行恰当归纳。
1.快照Sql生再加SqlNode信息,这个操作过程发生在对select、update等Sql操作符解操作过程。如果是快照Sql实际上不会把#{}替换再加?。
2.快照Sql解在换取BoundSql时候触发。不会函数调至用SqlNode的apply同步进行Sql解再加快照Sql,然后把#{}替换再加?,并绑定ParameterMapping射影。
录用读物:
MyBatis在实践中不会配置档案
Java研发基本概念之Mybatis入门基础性
java研发SSM基本概念构建之MyBatis快照SQL
。广州精神病专科医院哪家好重庆白癜风专科医院哪里好
山东妇科医院挂号咨询
天津妇科医院哪家好
职场双减cp英太青x7分甜甩痛舞
- 02-10港媒:中华人民共和国高铁已被“粪便淹没”!再不处理后果严重,是真的吗?
- 02-10因果是自身有缘的积累
- 02-10衰退警灯闪烁!策略师无视:美国经济或在明年初陷入严重衰退
- 02-10ASML没想到!30年所依赖的关键,北京师范大学实现突破还更加先进!
- 02-10齐一民《四十而大惑》刊载(16)幽默是天生的
- 02-10凯投宏观:美国股市也许在2024年大幅上涨
- 02-10滴天髓 论生时
- 02-10世界上最快的飞机!速度高达6.72马赫,X-15航天飞机是怎么明白的
- 02-10美国纽约州联合IBM与DRAM等芯片公司,将斥资100亿美元建立下一代半导体研发中心
- 02-10新型骗局来袭!近一周已有多人4人