MyBatis整合Spring的实现(13)

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

本章中分析insert元素的解析。

1 配置文件

<insert id="insert" parameterType="cn.vansky.schedule.time.menu.bo.Menu"><!--WARNING - @mbggeneratedThis element is automatically generated by MyBatis Generator, do not modify.This element was generated on Fri Aug 14 16:08:36 CST 2015.-->insert into tb_menu (menu_name, menu_remark, menu_parent_id, menu_url, is_show, is_delete, operation_user_name, operation_time)values (#{menuName,jdbcType=VARCHAR}, #{menuRemark,jdbcType=VARCHAR}, #{menuParentId,jdbcType=INTEGER}, #{menuUrl,jdbcType=VARCHAR}, #{isShow,jdbcType=TINYINT}, #{isDelete,jdbcType=TINYINT}, #{operationUserName,jdbcType=VARCHAR}, #{operationTime,jdbcType=TIMESTAMP})
</insert>

2 方法buildStatementFromContext

private void buildStatementFromContext(List<XNode> list) {if (configuration.getDatabaseId() != null) {buildStatementFromContext(list, configuration.getDatabaseId());}buildStatementFromContext(list, null);}private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {for (XNode context : list) {// 对一个SQL进行解析final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);try {statementParser.parseStatementNode();} catch (IncompleteElementException e) {configuration.addIncompleteStatement(statementParser);}}
}

上面是一个总的方法包括,insert、update、delete、select4中元素都会进入此方法。这里也会捕获一种异常,并把错误的解析放入Configuration(全局配置类)的Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>()。

3 方法parseStatementNode

public void parseStatementNode() {// insertString id = context.getStringAttribute("id");// nullString databaseId = context.getStringAttribute("databaseId");// 第一次检查这里是不通过的,直接跳过if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) return;// null Integer fetchSize = context.getIntAttribute("fetchSize");// nullInteger timeout = context.getIntAttribute("timeout");// nullString parameterMap = context.getStringAttribute("parameterMap");// cn.vansky.schedule.time.menu.bo.MenuString parameterType = context.getStringAttribute("parameterType");// class cn.vansky.schedule.time.menu.bo.MenuClass<?> parameterTypeClass = resolveClass(parameterType);// nullString resultMap = context.getStringAttribute("resultMap");// nullString resultType = context.getStringAttribute("resultType");// nullString lang = context.getStringAttribute("lang");// 获取默认的处理对象// org.apache.ibatis.scripting.xmltags.XMLLanguageDriverLanguageDriver langDriver = getLanguageDriver(lang);// nullClass<?> resultTypeClass = resolveClass(resultType);// nullString resultSetType = context.getStringAttribute("resultSetType");// PREPAREDStatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));// nullResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);// insertString nodeName = context.getNode().getNodeName();// INSERTSqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));// falseboolean isSelect = sqlCommandType == SqlCommandType.SELECT;// trueboolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);// falseboolean useCache = context.getBooleanAttribute("useCache", isSelect);// falseboolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);// Include Fragments before parsingXMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);// 解析<include refid="Base_Column_List" />includeParser.applyIncludes(context.getNode());// Parse selectKey after includes and remove them.processSelectKeyNodes(id, parameterTypeClass, langDriver);// 这里通过下面分析获取的SQL源(静态SQL源),因为没有动态标签SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);// nullString resultSets = context.getStringAttribute("resultSets");// nullString keyProperty = context.getStringAttribute("keyProperty");// nullString keyColumn = context.getStringAttribute("keyColumn");// org.apache.ibatis.executor.keygen.NoKeyGeneratorKeyGenerator keyGenerator;// insert!selectKeyString keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;// cn.vansky.schedule.time.menu.dao.MenuMapper.insert!selectKeykeyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);if (configuration.hasKeyGenerator(keyStatementId)) {keyGenerator = configuration.getKeyGenerator(keyStatementId);} else {keyGenerator = context.getBooleanAttribute("useGeneratedKeys",configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))? new Jdbc3KeyGenerator() : new NoKeyGenerator();}builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);}

方法XMLLanguageDriver.createSqlSource

public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);// 入参Class及节点解析return builder.parseScriptNode();
}

5 方法XMLScriptBuilder.parseScriptNode

public SqlSource parseScriptNode() {// 解析动态标签,if、where、forList<SqlNode> contents = parseDynamicTags(context);// 所有动态标签集合类MixedSqlNode rootSqlNode = new MixedSqlNode(contents);SqlSource sqlSource = null;if (isDynamic) {sqlSource = new DynamicSqlSource(configuration, rootSqlNode);} else {sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);}return sqlSource;
}

6 方法XMLScriptBuilder.parseDynamicTags

private List<SqlNode> parseDynamicTags(XNode node) {List<SqlNode> contents = new ArrayList<SqlNode>();// 获取动态标签与内容列表NodeList children = node.getNode().getChildNodes();for (int i = 0; i < children.getLength(); i++) {XNode child = node.newXNode(children.item(i));// 内容if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {String data = child.getStringBody("");// 内容SqlNodeTextSqlNode textSqlNode = new TextSqlNode(data);// 动态修改的内容if (textSqlNode.isDynamic()) {contents.add(textSqlNode);isDynamic = true;} else {// 静态内容contents.add(new StaticTextSqlNode(data));}} else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628// 节点为元素,也就是动态标签where、if、forString nodeName = child.getNode().getNodeName();// 获取动态标签处理器WhereHandler、ForEachHandlerNodeHandler handler = nodeHandlers.get(nodeName);if (handler == null) {throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");}// 处理器处理内容,并把处理的内容加入到SQLNodehandler.handleNode(child, contents);isDynamic = true;}}return contents;}

方法5中有2中数据源DynamicSqlSource(动态SQL源)和RawSqlSource(静态SQL源),动态SQL源就是包括where、if、for,静态SQL源就是只包括SQL语句,下面就简单分析一下2中SQL源。

RawSqlSource(静态SQL源)

public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);Class<?> clazz = parameterType == null ? Object.class : parameterType;sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<String, Object>());
}
public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {// 参数处理MappingParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);// 解析XML中的SQL语句,#{menuName,jdbcType=VARCHAR},转换成?及对应的处理类型ParameterMappingString sql = parser.parse(originalSql);return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

这里直接解析并生成StaticSqlSource,包括SQL语句及对应的处理类型。

7.1 ParameterMapping对应的menuName

/** 全局配置类 */
private Configuration configuration;
/** menuName */
private String property;
/** IN:输入 */
private ParameterMode mode;
/** class java.lang.String */
private Class<?> javaType = Object.class;
/** VARCHAR */
private JdbcType jdbcType;
/** null */
private Integer numericScale;
/** StringTypeHandler */
private TypeHandler<?> typeHandler;
/** null */
private String resultMapId;
/** null */
private String jdbcTypeName;
/** null */
private String expression;

DynamicSqlSource(动态SQL源)

public DynamicSqlSource(Configuration configuration, SqlNode rootSqlNode) {this.configuration = configuration;this.rootSqlNode = rootSqlNode;
}

很明显这里没有进行生成SQL,那就是在具体获取SQL时进行生成SQL

9 方法addMappedStatement

此方法只是赋值,没有什么特殊处理,所以此方法不在分析,可以自行研究。

总结 

附上图片MappedStatement属性值

171709_MpGF_1269959.png

171749_VZbi_1269959.png

下面给出动态SQL源的MappedStatement属性值

<insert id="insertSelective" parameterType="cn.vansky.schedule.time.menu.bo.Menu"><!--WARNING - @mbggeneratedThis element is automatically generated by MyBatis Generator, do not modify.This element was generated on Fri Aug 14 16:08:36 CST 2015.-->insert into tb_menu<trim prefix="(" suffix=")" suffixOverrides=","><if test="menuName != null">menu_name,</if><if test="menuRemark != null">menu_remark,</if><if test="menuParentId != null">menu_parent_id,</if><if test="menuUrl != null">menu_url,</if><if test="isShow != null">is_show,</if><if test="isDelete != null">is_delete,</if><if test="operationUserName != null">operation_user_name,</if><if test="operationTime != null">operation_time,</if></trim><trim prefix="values (" suffix=")" suffixOverrides=","><if test="menuName != null">#{menuName,jdbcType=VARCHAR},</if><if test="menuRemark != null">#{menuRemark,jdbcType=VARCHAR},</if><if test="menuParentId != null">#{menuParentId,jdbcType=INTEGER},</if><if test="menuUrl != null">#{menuUrl,jdbcType=VARCHAR},</if><if test="isShow != null">#{isShow,jdbcType=TINYINT},</if><if test="isDelete != null">#{isDelete,jdbcType=TINYINT},</if><if test="operationUserName != null">#{operationUserName,jdbcType=VARCHAR},</if><if test="operationTime != null">#{operationTime,jdbcType=TIMESTAMP},</if></trim>
</insert>

172809_JDRT_1269959.png

其实这里属性都差不多,主要是SqlSource不一样,那么下来就看它的属性。

180259_nAOr_1269959.png

180530_fIhy_1269959.png

转载于:https://my.oschina.net/u/1269959/blog/523651

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544009.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

麻了,代码改成多线程,竟有9大问题

很多时候&#xff0c;我们为了提升接口的性能&#xff0c;会把之前单线程同步执行的代码&#xff0c;改成多线程异步执行。比如&#xff1a;查询用户信息接口&#xff0c;需要返回用户基本信息、积分信息、成长值信息&#xff0c;而用户、积分和成长值&#xff0c;需要调用不同…

浅聊一下线程池的10个坑

日常开发中&#xff0c;为了更好管理线程资源&#xff0c;减少创建线程和销毁线程的资源损耗&#xff0c;我们会使用线程池来执行一些异步任务。但是线程池使用不当&#xff0c;就可能会引发生产事故。今天跟大家聊聊线程池的10个坑。大家看完肯定会有帮助的~线程池默认使用无界…

Linux命令行上执行操作,不退回命令行的解决方法

问题描述&#xff1a; 如果你现在登录Centos执行了某个操作&#xff0c;但是操作一直占用命令行&#xff0c;命令行显示的也都是这个命令相关的操作&#xff0c;我想做其它事情 &#xff0c;该怎么办呢 &#xff1f; 解决方法&#xff1a; 根据《Linux命令行与Shell编程大全第2…

SpringBoot 读取配置文件的 5 种方法!

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;Spring Boot 中读取配置文件有以下 5 种方法&#xff1a;使用 Value 读取配置文件。使用 ConfigurationProperties 读…

使用阿里巴巴 Druid 轻松实现加密!

作者 | 磊哥来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;为什么要加密&#xff1f;现在的开发习惯&#xff0c;无论是公司的项目还是个人的项目&#xff0c;都会选择将源码上传到 Gi…

xml不显示css样式_如何使用CSS显示XML?

xml不显示css样式Introduction: 介绍&#xff1a; You must be aware of the term XML and must have dealt with these various XML files while developing a web page or website. This article focuses entirely on XML and how to display them using CSS. There are num…

c#组元(Tuple)的使用

组元(Tuple)是C# 4.0引入的一个新特性&#xff0c;可以在.NET Framework 4.0或更高版本中使用。组元使用泛型来简化类的定义&#xff0c;多用于方法的返回值。在函数需要返回多个类型的时候&#xff0c;就不必使用out , ref等关键字了&#xff0c;直接定义一个Tuple类型&#x…

浅谈一下 MyBatis 批量插入的 3 种方法!

作者 | 磊哥来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone批量插入功能是我们日常工作中比较常见的业务功能之一&#xff0c;今天咱们来一个 MyBatis 批量插入的汇总篇&#xff0c;同时对 3 种实现…

快速搭建 SpringCloud Alibaba Nacos 配置中心!

作者 | 磊哥来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;Spring Cloud Alibaba 是阿里巴巴提供的一站式微服务开发解决方案&#xff0c;目前已被 Spring Cloud 官方收录。而 Nacos 作…

浅聊一下建表的15个小技巧

前言对于后端开发同学来说&#xff0c;访问数据库&#xff0c;是代码中必不可少的一个环节。系统中收集到用户的核心数据&#xff0c;为了安全性&#xff0c;我们一般会存储到数据库&#xff0c;比如&#xff1a;mysql&#xff0c;oracle等。后端开发的日常工作&#xff0c;需要…

JConsole的使用手册 JDK1.5(转)

一篇Sun项目主页上介绍JConsole使用的文章&#xff0c;前段时间性能测试的时候大概翻译了一下以便学习&#xff0c;今天整理一下发上来&#xff0c;有些地方也不知道怎么翻&#xff0c;就保留了原文&#xff0c;可能还好理解点&#xff0c;呵呵&#xff0c;水平有限&#xff0c…

一文快速上手 Nacos 注册中心+配置中心!

作者 | 磊哥来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;Spring Cloud Alibaba 是阿里巴巴提供的一站式微服务开发解决方案&#xff0c;目前已被 Spring Cloud 官方收录。而 Nacos 作…

所有子序列的逆序对总和_一个数字的所有子串的总和

所有子序列的逆序对总和Problem statement: 问题陈述&#xff1a; Given an integer, S represented as a string, get the sum of all possible substrings of this string. 给定一个以字符串形式表示的整数S &#xff0c;得到该字符串所有可能的子字符串的和 。 Input: 输入…

synchronized:使用不规范,老板泪两行!

线程安全问题一直是系统亘古不变的痛点。这不&#xff0c;最近在项目中发了一个错误使用线程同步的案例。表面上看已经使用了同步机制&#xff0c;一切岁月静好&#xff0c;但实际上线程同步却毫无作用。关于线程安全的问题&#xff0c;基本上就是在挖坑与填坑之间博弈&#xf…

SQL --运算符

2019独角兽企业重金招聘Python工程师标准>>> 一、<> (安全等于运算符) mysql中的 、<>或!运算符&#xff0c;相信大家已经很清楚了。今天看到了<>这个运算符&#xff0c;记录下来。 1><>和号的相同点 他们都是两个值比较符&#xff0c;相…

linux 文件浏览器_浏览Linux文件系统

linux 文件浏览器你为什么要学习&#xff1f; (Why would you want to learn?) Linux is probably the most used operating system when it comes to development. For a developer, Linux provides all the required tools. Learning how to navigate the Linux file system…

@Autowired 和 @Resource 的 5 点区别!

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;Autowired 和 Resource 都是 Spring/Spring Boot 项目中&#xff0c;用来进行依赖注入的注解。它们都提供了将依赖对…

rsync同步数据到内网

最近公司要求将IDC的APP日志备份到公司办公网内部&#xff0c;思前想后&#xff0c;结合以前学过的知识&#xff0c;决定用rsync直接推送&#xff0c;即从APP服务器上直接将日志推送到公司内网。这样避免了在生产服务器上额外安装更多软件而且只需要进行简单的配置&#xff0c;…

SpringBoot 时间格式化的 5 种实现方法!

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;在我们日常工作中&#xff0c;时间格式化是一件经常遇到的事儿&#xff0c;所以本文我们就来盘点一下 Spring Boot 中时间格…

SpringBoot 解决跨域问题的 5 种方案!

作者 | 磊哥来源 | Java面试真题解析&#xff08;ID&#xff1a;aimianshi666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;跨域问题指的是不同站点之间&#xff0c;使用 ajax 无法相互调用的问题。跨域问题本质是浏览器的一种保护机制&#…