当前位置: 首页 > news >正文

网站备案号几位数字 沪分销商城功能

网站备案号几位数字 沪,分销商城功能,横店网站开发,太原网站建设制作报价转载自 mybatis源码阅读(三)#xff1a;mybatis初始化#xff08;下#xff09;mapper解析 MyBatis 的真正强大在于它的映射语句#xff0c;也是它的魔力所在。由于它的异常强大#xff0c;映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比…转载自 mybatis源码阅读(三)mybatis初始化下mapper解析 MyBatis 的真正强大在于它的映射语句也是它的魔力所在。由于它的异常强大映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比你会立即发现省掉了将近 95% 的代码。MyBatis 就是针对 SQL 构建的并且比普通的方法做的更好。 SQL 映射文件有很少的几个顶级元素按照它们应该被定义的顺序 cache – 给定命名空间的缓存配置。cache-ref – 其他命名空间缓存配置的引用。resultMap – 是最复杂也是最强大的元素用来描述如何从数据库结果集中来加载对象。parameterMap – 已废弃老式风格的参数映射。内联参数是首选,这个元素可能在将来被移除这里不会记录。sql – 可被其他语句引用的可重用语句块。insert – 映射插入语句update – 映射更新语句delete – 映射删除语句select – 映射查询语句 对每个标签的属性以及作用这里不做解释 可以参考官方文档http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html 上一篇文章介绍了mybatis配置文件解析mappers节点的源码中有如下语句从这里得到mapper映射文件时通过XMLMapperBuilder解析的。 一、XMLMapperBuilder //mapper映射文件都是通过XMLMapperBuilder解析XMLMapperBuilder mapperParser new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());mapperParser.parse(); //解析mapper文件 public void parse() {// 判断是否已经加载过改映射文件if (!configuration.isResourceLoaded(resource)) {// 处理mapper节点configurationElement(parser.evalNode(/mapper));// 将resource添加到configuration的loadedResources集合中保存 它是HashSetStringconfiguration.addLoadedResource(resource);//注册mapper接口bindMapperForNamespace();}// 处理解析失败的resultMap节点parsePendingResultMaps();// 处理解析失败的cache-ref节点parsePendingCacheRefs();// 处理解析失败的sql节点parsePendingStatements(); } private void configurationElement(XNode context) {try {String namespace context.getStringAttribute(namespace);if (namespace null || namespace.equals()) {throw new BuilderException(Mappers namespace cannot be empty);}// 记录当前命名空间builderAssistant.setCurrentNamespace(namespace);// 解析cache-ref节点cacheRefElement(context.evalNode(cache-ref));// 解析cache节点cacheElement(context.evalNode(cache));// 解析parameterMap节点这个已经被废弃不推荐使用parameterMapElement(context.evalNodes(/mapper/parameterMap));// 解析resultMap节点resultMapElements(context.evalNodes(/mapper/resultMap));// 解析sql节点sqlElement(context.evalNodes(/mapper/sql));// 解析statement buildStatementFromContext(context.evalNodes(select|insert|update|delete));} catch (Exception e) {throw new BuilderException(Error parsing Mapper XML. The XML location is resource . Cause: e, e);} } 1.cache节点 它通过调用CacheBuilder的相应方法完成cache的创建。每个cache内部都有一个唯一的ID这个id的值就是namespace。创建好的cache对象存入configuration的cache缓存中该缓存以cache的ID属性即namespace为key这里再次体现了mybatis的namespace的强大用处。 /*** cache- 配置本定命名空间的缓存。* type- cache实现类默认为PERPETUAL可以使用自定义的cache实现类别名或完整类名皆可* eviction- 回收算法默认为LRU可选的算法有* LRU– 最近最少使用的移除最长时间不被使用的对象。* FIFO– 先进先出按对象进入缓存的顺序来移除它们。* SOFT– 软引用移除基于垃圾回收器状态和软引用规则的对象。* WEAK– 弱引用更积极地移除基于垃圾收集器状态和弱引用规则的对象。* flushInterval- 刷新间隔默认为1个小时单位毫秒* size- 缓存大小默认大小1024单位为引用数* readOnly- 只读* param context* throws Exception*/ private void cacheElement(XNode context) throws Exception {if (context ! null) {String type context.getStringAttribute(type, PERPETUAL);Class? extends Cache typeClass typeAliasRegistry.resolveAlias(type);String eviction context.getStringAttribute(eviction, LRU);Class? extends Cache evictionClass typeAliasRegistry.resolveAlias(eviction);Long flushInterval context.getLongAttribute(flushInterval);Integer size context.getIntAttribute(size);boolean readWrite !context.getBooleanAttribute(readOnly, false);boolean blocking context.getBooleanAttribute(blocking, false);Properties props context.getChildrenAsProperties();builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);} } public Cache useNewCache(Class? extends Cache typeClass,Class? extends Cache evictionClass,Long flushInterval,Integer size,boolean readWrite,boolean blocking,Properties props) {Cache cache new CacheBuilder(currentNamespace).implementation(valueOrDefault(typeClass, PerpetualCache.class)).addDecorator(valueOrDefault(evictionClass, LruCache.class)).clearInterval(flushInterval).size(size).readWrite(readWrite).blocking(blocking).properties(props).build();configuration.addCache(cache);currentCache cache;return cache; } 2.cache-ref节点 cacheRefElement方法负责解析cache-ref元素它通过调用CacheRefResolver的相应方法完成cache的引用。创建好的cache-ref引用关系存入configuration的cacheRefMap缓存中。 /*** cache-ref–从其他命名空间引用缓存配置。* 如果你不想定义自己的cache可以使用cache-ref引用别的cache。* 因为每个cache都以namespace为id* 所以cache-ref只需要配置一个namespace属性就可以了。* 需要注意的是如果cache-ref和cache都配置了以cache为准。* param context*/ private void cacheRefElement(XNode context) {if (context ! null) {configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute(namespace));CacheRefResolver cacheRefResolver new CacheRefResolver(builderAssistant, context.getStringAttribute(namespace));try {cacheRefResolver.resolveCacheRef();} catch (IncompleteElementException e) {configuration.addIncompleteCacheRef(cacheRefResolver);}} } 3.resultMap节点 resultMapElement方法负责解析resultMap元素它通过调用ResultMapResolver的相应方法完成resultMap的解析。resultMap节点下除了discriminator子节点的其他子节点都会解析成对应的ResultMapping对象而每个resultMap节点都会被解析成一个ResultMap对象创建好的resultMap存入configuration的resultMaps缓存中该缓存以namespaceresultMap的id为key这里再次体现了mybatis的namespace的强大用处。 private void resultMapElements(ListXNode list) throws Exception {for (XNode resultMapNode : list) {try {resultMapElement(resultMapNode);} catch (IncompleteElementException e) {// ignore, it will be retried}} }private ResultMap resultMapElement(XNode resultMapNode) throws Exception {return resultMapElement(resultMapNode, Collections.ResultMapping emptyList()); }private ResultMap resultMapElement(XNode resultMapNode, ListResultMapping additionalResultMappings) throws Exception {ErrorContext.instance().activity(processing resultMapNode.getValueBasedIdentifier());String id resultMapNode.getStringAttribute(id,resultMapNode.getValueBasedIdentifier());String type resultMapNode.getStringAttribute(type,resultMapNode.getStringAttribute(ofType,resultMapNode.getStringAttribute(resultType,resultMapNode.getStringAttribute(javaType))));String extend resultMapNode.getStringAttribute(extends);Boolean autoMapping resultMapNode.getBooleanAttribute(autoMapping);Class? typeClass resolveClass(type);Discriminator discriminator null;ListResultMapping resultMappings new ArrayListResultMapping();resultMappings.addAll(additionalResultMappings);ListXNode resultChildren resultMapNode.getChildren();for (XNode resultChild : resultChildren) {if (constructor.equals(resultChild.getName())) {processConstructorElement(resultChild, typeClass, resultMappings);} else if (discriminator.equals(resultChild.getName())) {discriminator processDiscriminatorElement(resultChild, typeClass, resultMappings);} else {ListResultFlag flags new ArrayListResultFlag();if (id.equals(resultChild.getName())) {flags.add(ResultFlag.ID);}resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));}}ResultMapResolver resultMapResolver new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);try {return resultMapResolver.resolve();} catch (IncompleteElementException e) {configuration.addIncompleteResultMap(resultMapResolver);throw e;} } 4.sql节点解析 sql节点用来定义可重用的sql语句片段 sqlElement方法负责解析sql元素。id属性用于区分不同的sql元素在同一个mapper配置文件中可以配置多个sql元素。 private void sqlElement(ListXNode list) throws Exception {if (configuration.getDatabaseId() ! null) {sqlElement(list, configuration.getDatabaseId());}sqlElement(list, null); }private void sqlElement(ListXNode list, String requiredDatabaseId) throws Exception {for (XNode context : list) {String databaseId context.getStringAttribute(databaseId);String id context.getStringAttribute(id);id builderAssistant.applyCurrentNamespace(id, false);if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {// 记录到sqlFragments中保存其实 构造函数中可以看到该字段指向了configuration的sqlFragments集合中sqlFragments.put(id, context);}} }private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) {if (requiredDatabaseId ! null) {if (!requiredDatabaseId.equals(databaseId)) {return false;}} else {if (databaseId ! null) {return false;}// skip this fragment if there is a previous one with a not null databaseIdif (this.sqlFragments.containsKey(id)) {XNode context this.sqlFragments.get(id);if (context.getStringAttribute(databaseId) ! null) {return false;}}}return true; } 二、XMLStatementBuilder 映射配置文件中还有一类比较重要的节点需要解析其实就是select|insert|update|delete 节点这些节点主要用于定义SQL语句他们不在由XMLMapperBuilder进行解析而是由XMLStatementBuilder负责进行解析每个节点会被解析成MappedStatement对象并存入到configuration对象中去。在这个方法内有几个重要的步骤理解他们对正确的配置statement元素很有帮助。 1.MappedStatement MappedStatement包含了这些节点的很多属性其中比较重要的如下 private String resource;//节点中的id 包括命名空间 private SqlSource sqlSource;//SqlSource对象对应一条SQL语句 private SqlCommandType sqlCommandType;//SQL的类型insertdeleteselectupdate 解析过程代码如下 public void parseStatementNode() {// 获取sql节点的id以及databaseId如果和当前不匹配不加载改节点// 如果存在id相同且databaseId不为空的节点也不在加载改节点String id context.getStringAttribute(id);String databaseId context.getStringAttribute(databaseId);if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {return;}// 获取节点的多种属性Integer fetchSize context.getIntAttribute(fetchSize);Integer timeout context.getIntAttribute(timeout);String parameterMap context.getStringAttribute(parameterMap);String parameterType context.getStringAttribute(parameterType);Class? parameterTypeClass resolveClass(parameterType);String resultMap context.getStringAttribute(resultMap);String resultType context.getStringAttribute(resultType);String lang context.getStringAttribute(lang);LanguageDriver langDriver getLanguageDriver(lang);Class? resultTypeClass resolveClass(resultType);String resultSetType context.getStringAttribute(resultSetType);StatementType statementType StatementType.valueOf(context.getStringAttribute(statementType, StatementType.PREPARED.toString()));ResultSetType resultSetTypeEnum resolveResultSetType(resultSetType);// 根据节点的名称设置sqlCommandType的类型String nodeName context.getNode().getNodeName();SqlCommandType sqlCommandType SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));boolean isSelect sqlCommandType SqlCommandType.SELECT;boolean flushCache context.getBooleanAttribute(flushCache, !isSelect);boolean useCache context.getBooleanAttribute(useCache, isSelect);boolean resultOrdered context.getBooleanAttribute(resultOrdered, false);// 在解析SQL语句之前先处理include节点XMLIncludeTransformer includeParser new XMLIncludeTransformer(configuration, builderAssistant);includeParser.applyIncludes(context.getNode());// 处理selectKey节点processSelectKeyNodes(id, parameterTypeClass, langDriver);// 完成节点的解析 该部分是核心SqlSource sqlSource langDriver.createSqlSource(configuration, context, parameterTypeClass);// 获取resultSets keyProperty keyColumn三个属性String resultSets context.getStringAttribute(resultSets);String keyProperty context.getStringAttribute(keyProperty);String keyColumn context.getStringAttribute(keyColumn);KeyGenerator keyGenerator;// 获取selectKey节点对应的selectKeyGenerator的idString keyStatementId id SelectKeyGenerator.SELECT_KEY_SUFFIX;keyStatementId builderAssistant.applyCurrentNamespace(keyStatementId, true);if (configuration.hasKeyGenerator(keyStatementId)) {keyGenerator configuration.getKeyGenerator(keyStatementId);} else {keyGenerator context.getBooleanAttribute(useGeneratedKeys,configuration.isUseGeneratedKeys() SqlCommandType.INSERT.equals(sqlCommandType))? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;}// 通过MapperBuilderAssistant创建MappedStatement对象// 并添加到configuration.mappedStatements集合中保存builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,resultSetTypeEnum, flushCache, useCache, resultOrdered, keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets); } 2、解析include节点 在解析statement节点之前首先通过XMLIncludeTransformer解析include节点改过程会将include节点替换sql节点中定义的sql片段并将其中的${xx}占位符换成真实的参数 private void applyIncludes(Node source, final Properties variablesContext, boolean included) {if (source.getNodeName().equals(include)) { // ---(2)处理include节点// 查找refid属性指向的sql返回的是深克隆的Node对象Node toInclude findSqlFragment(getStringAttribute(source, refid), variablesContext);Properties toIncludeContext getVariablesContext(source, variablesContext);//递归处理include节点applyIncludes(toInclude, toIncludeContext, true);if (toInclude.getOwnerDocument() ! source.getOwnerDocument()) {toInclude source.getOwnerDocument().importNode(toInclude, true);}// 将include节点替换sql节点source.getParentNode().replaceChild(toInclude, source);while (toInclude.hasChildNodes()) {// 将sql节点的子节点添加到sql节点的前面toInclude.getParentNode().insertBefore(toInclude.getFirstChild(), toInclude);}// 替换后删除sql节点toInclude.getParentNode().removeChild(toInclude);} else if (source.getNodeType() Node.ELEMENT_NODE) {// ---(1)if (included !variablesContext.isEmpty()) {// replace variables in attribute valuesNamedNodeMap attributes source.getAttributes();for (int i 0; i attributes.getLength(); i) {// 遍历当前sql的子节点Node attr attributes.item(i);attr.setNodeValue(PropertyParser.parse(attr.getNodeValue(), variablesContext));}}NodeList children source.getChildNodes();for (int i 0; i children.getLength(); i) {applyIncludes(children.item(i), variablesContext, included);}} else if (included source.getNodeType() Node.TEXT_NODE !variablesContext.isEmpty()) {// ---(3)// replace variables in text node 替换对应的占位符source.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext));} } 3、解析selectKey节点 在insertupdate节点中可以定义selectKey节点来解决主键自增问题。 private void parseSelectKeyNode(String id, XNode nodeToHandle, Class? parameterTypeClass, LanguageDriver langDriver, String databaseId) {String resultType nodeToHandle.getStringAttribute(resultType);Class? resultTypeClass resolveClass(resultType);StatementType statementType StatementType.valueOf(nodeToHandle.getStringAttribute(statementType, StatementType.PREPARED.toString()));String keyProperty nodeToHandle.getStringAttribute(keyProperty);String keyColumn nodeToHandle.getStringAttribute(keyColumn);boolean executeBefore BEFORE.equals(nodeToHandle.getStringAttribute(order, AFTER));//defaultsboolean useCache false;boolean resultOrdered false;KeyGenerator keyGenerator NoKeyGenerator.INSTANCE;Integer fetchSize null;Integer timeout null;boolean flushCache false;String parameterMap null;String resultMap null;ResultSetType resultSetTypeEnum null;// 生成SqlSourceSqlSource sqlSource langDriver.createSqlSource(configuration, nodeToHandle, parameterTypeClass);// selectKey节点中只能配置select语句SqlCommandType sqlCommandType SqlCommandType.SELECT;// 创建MappedStatement对象并添加到configuration的mappedStatements集合中保存builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,resultSetTypeEnum, flushCache, useCache, resultOrdered,keyGenerator, keyProperty, keyColumn, databaseId, langDriver, null);id builderAssistant.applyCurrentNamespace(id, false);MappedStatement keyStatement configuration.getMappedStatement(id, false);// 创建对应的KeyGenerator(主键自增策略)添加到configuration中configuration.addKeyGenerator(id, new SelectKeyGenerator(keyStatement, executeBefore)); } 三、绑定Mapper接口 每个映射配置文件的命名空间可以绑定一个Mapper接口并注册到MapperRegistry中。 // 绑定mapper接口 private void bindMapperForNamespace() {//获取映射文件的命名空间String namespace builderAssistant.getCurrentNamespace();if (namespace ! null) {Class? boundType null;try {// 解析命名空间对应的类型 即daoboundType Resources.classForName(namespace);} catch (ClassNotFoundException e) {//ignore, bound type is not required}if (boundType ! null) {if (!configuration.hasMapper(boundType)) {// 是否已经加载了// Spring may not know the real resource name so we set a flag// to prevent loading again this resource from the mapper interface// look at MapperAnnotationBuilder#loadXmlResource//注册configuration.addLoadedResource(namespace: namespace);configuration.addMapper(boundType);}}} }
http://www.zqtcl.cn/news/222283/

相关文章:

  • 阜阳网站是网站开发与设计专业
  • 网站建设哪个品牌好网站新备案不能访问
  • 网站备案号申请流程华为企业文化
  • 服装网站目标互联网舆情报告
  • 1.网站开发的详细流程电商网站开发文档
  • 域名估价网站制作网站需要注意什么
  • 新浪云虚拟主机做电影网站用什么l软件做网站了
  • 方城网站建设猴痘的治疗方法
  • 做响应式网站有什么插件哔哩哔哩免费安装
  • 织梦网站默认密码wordpress菜单页和文章页路径不同
  • 那些网站可以做兼职网站建设与维护 东博
  • 快速建站的模板建设银行嘉兴分行官方网站
  • 江西智能网站建设wordpress三栏博客主题
  • 怎么做网站账号注册机sem竞价
  • 吕梁建设机械网站怎么让网站排名上去
  • 网站建设的需要分析龙岗招聘网
  • 如何制作企业的网站网站开发答辩ppt
  • 大连中山网站建设网站在线qq代码
  • 南昌seo网站微商城网站建设如何
  • anker 网站建设手机可以做网站的服务器吗
  • 门户网站建设 报价没有网页快照对网站有什么影响
  • 陕西专业网站建设哪家好甜点网站里的新闻资讯怎么做
  • 邯郸企业网站团队h5微场景制作软件
  • 镇江建工建设集团网站泛微e8做网站门户
  • 适合友情链接的网站全球软件公司排行榜
  • 沈阳网站制作 600元网站飘动广告代码
  • 最先进的无锡网站建设wordpress调用 别的网站
  • 河南网站备案地址静安青岛网站建设
  • 烟台网站建设推荐企汇互联见效付款查看网站被百度收录
  • 做标签网站360街景地图怎么看