mybatis源码阅读(七) ---ResultSetHandler了解一下

转载自  mybatis源码阅读(七) ---ResultSetHandler了解一下

1、MetaObject

MetaObject用于反射创建对象、反射从对象中获取属性值、反射给对象设置属性值,参数设置和结果封装,用的都是这个MetaObject提供的功能。

public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {if (object == null) {return SystemMetaObject.NULL_META_OBJECT;} else {return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);}
}
public Object getValue(String name) {PropertyTokenizer prop = new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());if (metaValue == SystemMetaObject.NULL_META_OBJECT) {return null;} else {return metaValue.getValue(prop.getChildren());}} else {return objectWrapper.get(prop);}
}public void setValue(String name, Object value) {PropertyTokenizer prop = new PropertyTokenizer(name);if (prop.hasNext()) {MetaObject metaValue = metaObjectForProperty(prop.getIndexedName());if (metaValue == SystemMetaObject.NULL_META_OBJECT) {if (value == null && prop.getChildren() != null) {// don't instantiate child path if value is nullreturn;} else {metaValue = objectWrapper.instantiatePropertyValue(name, prop, objectFactory);}}metaValue.setValue(prop.getChildren(), value);} else {objectWrapper.set(prop, value);}
}

Object object:要反射的对象,比如Student。

ObjectFactory objectFactory:通过Class对象反射创建对象实例的工厂类,比如创建一个User对象。

ObjectWrapperFactory :对目标对象进行包装,比如可以将Properties对象包装成为一个Map并返回Map对象。

ReflectorFactory :为了避免多次反射同一个Class对象,ReflectorFactory提供了Class对象的反射结果缓存。

getValue(String name):属性取值。

setValue(String name, Object value):属性赋值。

2、结果封装实现原理

Mybatis的结果封装,分为两种,一种是有ResultMap映射表,明确定义了结果集列名与对象属性名的配对关系,另外一种是对象类型,没有明确定义结果集列名与对象属性名的配对关系,如resultType是User对象。

<resultMap type="userT" id="userResult"><id property="id" column="t_id"/><result property="name" column="name" />
</resultMap><select id="findUserById" resultMap="userResult">select * from m_user where id = #{id}
</select>

原理非常简单:使用ObjectFactory ,创建一个userT对象实例。

userT.setId(resultSet.getInt("t_id"));

userT.setName(resultSet.getString("name"));

如果是对象类型,如User对象类似,原理也非常简单。

<select id="findUserById" resultType="com.lpf.entity.User">select * from m_user where id = #{id}
</select>

原理:使用ObjectFactory ,创建一个User对象实例。

user.setId(resultSet.getInt("id"));user.setName(resultSet.getString("name"));


3、DefaultResultSetHandler

DefaultResultSetHandler继承了,ResultSetHandler是一个接口,提供了两个函数分别用来处理普通操作和存储过程的结果,
源码如下:

/*** @author Clinton Begin*/
public interface ResultSetHandler {<E> List<E> handleResultSets(Statement stmt) throws SQLException;<E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;void handleOutputParameters(CallableStatement cs) throws SQLException;}

DefaultResultSetHandler,其实现的步骤就是将Statement执行后的结果集,按照Mapper文件中配置的ResultType或ResultMap来封装成对应的对象,最后将封装的对象返回即可,

结果封装实现原理


DefaultResultSetHandler部分源码如下:

public class DefaultResultSetHandler implements ResultSetHandler {private static final Object DEFERED = new Object();// 此Map用来保存当前层级内部的结果对象(一对多关系的多方对象),key为combinedKeyprivate final Map<CacheKey, Object> nestedResultObjects = new HashMap<CacheKey, Object>();// 此Map用来保存当前层级的根对象(一对多关系中的一方对象),key为absoluteKeyprivate final Map<String, Object> ancestorObjects = new HashMap<String, Object>();private Object previousRowValue;// multiple resultsetsprivate final Map<String, ResultMapping> nextResultMaps = new HashMap<String, ResultMapping>();private final Map<CacheKey, List<PendingRelation>> pendingRelations = new HashMap<CacheKey, List<PendingRelation>>();// Cached Automappingsprivate final Map<String, List<UnMappedColumnAutoMapping>> autoMappingsCache = new HashMap<String, List<UnMappedColumnAutoMapping>>();// temporary marking flag that indicate using constructor mapping (use field to reduce memory usage)private boolean useConstructorMappings;private final PrimitiveTypes primitiveTypes;private static class PendingRelation {public MetaObject metaObject;public ResultMapping propertyMapping;}/*** 调用存储过程返回结果,将结果值放在参数中* @param cs* @throws SQLException*/@Overridepublic void handleOutputParameters(CallableStatement cs) throws SQLException {final Object parameterObject = parameterHandler.getParameterObject();final MetaObject metaParam = configuration.newMetaObject(parameterObject);final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();for (int i = 0; i < parameterMappings.size(); i++) {final ParameterMapping parameterMapping = parameterMappings.get(i);if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {if (ResultSet.class.equals(parameterMapping.getJavaType())) {handleRefCursorOutputParameter((ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);} else {final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));}}}}/***  对普通查询到的结果转换* @param stmt* @return* @throws SQLException*/@Overridepublic List<Object> handleResultSets(Statement stmt) throws SQLException {ErrorContext.instance().activity("handling results").object(mappedStatement.getId());final List<Object> multipleResults = new ArrayList<Object>();int resultSetCount = 0;//获取第一个结果值ResultSetWrapper rsw = getFirstResultSet(stmt);//获得resultMapList<ResultMap> resultMaps = mappedStatement.getResultMaps();//这边应该为1吧,一般resultMap为一个int resultMapCount = resultMaps.size();//判断是否有resultMap,没有的话抛出异常validateResultMapsCount(rsw, resultMapCount);while (rsw != null && resultMapCount > resultSetCount) {//获得resultMap,实体类和表中数据字段的对应关系ResultMap resultMap = resultMaps.get(resultSetCount);//将值设置成对应的resultmap对象handleResultSet(rsw, resultMap, multipleResults, null);rsw = getNextResultSet(stmt);cleanUpAfterHandlingResultSet();resultSetCount++;}//获得resultSetsString[] resultSets = mappedStatement.getResultSets();if (resultSets != null) {while (rsw != null && resultSetCount < resultSets.length) {ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);if (parentMapping != null) {String nestedResultMapId = parentMapping.getNestedResultMapId();ResultMap resultMap = configuration.getResultMap(nestedResultMapId);handleResultSet(rsw, resultMap, null, parentMapping);}rsw = getNextResultSet(stmt);cleanUpAfterHandlingResultSet();resultSetCount++;}}return collapseSingleResultList(multipleResults);}//获得第一个值,并将值打包private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {ResultSet rs = stmt.getResultSet();while (rs == null) {// move forward to get the first resultset in case the driver// doesn't return the resultset as the first result (HSQLDB 2.1)if (stmt.getMoreResults()) {rs = stmt.getResultSet();} else {if (stmt.getUpdateCount() == -1) {// no more results. Must be no resultsetbreak;}}}return rs != null ? new ResultSetWrapper(rs, configuration) : null;}//获取下一个值,将值打包private ResultSetWrapper getNextResultSet(Statement stmt) throws SQLException {// Making this method tolerant of bad JDBC driverstry {if (stmt.getConnection().getMetaData().supportsMultipleResultSets()) {// Crazy Standard JDBC way of determining if there are more resultsif (!(!stmt.getMoreResults() && stmt.getUpdateCount() == -1)) {ResultSet rs = stmt.getResultSet();if (rs == null) {return getNextResultSet(stmt);} else {return new ResultSetWrapper(rs, configuration);}}}} catch (Exception e) {// Intentionally ignored.}return null;}//关闭resultSetprivate void closeResultSet(ResultSet rs) {try {if (rs != null) {rs.close();}} catch (SQLException e) {// ignore}}//校验结果的resultMap,如果没有的话就抛出异常private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) {if (rsw != null && resultMapCount < 1) {throw new ExecutorException("A query was run and no Result Maps were found for the Mapped Statement '" + mappedStatement.getId()+ "'.  It's likely that neither a Result Type nor a Result Map was specified.");}}private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {try {if (parentMapping != null) {handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);} else {if (resultHandler == null) {DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);//将查询到的每个字段和Bean实体中的属性对应起来,生成一个Result对象handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);//结果映射对象及值添加到multipleResults中multipleResults.add(defaultResultHandler.getResultList());} else {handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);}}} finally {// issue #228 (close resultsets)closeResultSet(rsw.getResultSet());}}//操作列值public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {if (resultMap.hasNestedResultMaps()) {ensureNoRowBounds();checkResultHandler();handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);} else {handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);}}//判断记录行数private void ensureNoRowBounds() {if (configuration.isSafeRowBoundsEnabled() && rowBounds != null && (rowBounds.getLimit() < RowBounds.NO_ROW_LIMIT || rowBounds.getOffset() > RowBounds.NO_ROW_OFFSET)) {throw new ExecutorException("Mapped Statements with nested result mappings cannot be safely constrained by RowBounds. "+ "Use safeRowBoundsEnabled=false setting to bypass this check.");}}private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)throws SQLException {DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();skipRows(rsw.getResultSet(), rowBounds);while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);Object rowValue = getRowValue(rsw, discriminatedResultMap);storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());}}private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {final ResultLoaderMap lazyLoader = new ResultLoaderMap();Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {final MetaObject metaObject = configuration.newMetaObject(rowValue);boolean foundValues = this.useConstructorMappings;if (shouldApplyAutomaticMappings(resultMap, false)) {foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;}foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;foundValues = lazyLoader.size() > 0 || foundValues;rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;}return rowValue;}private Object getPropertyMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)throws SQLException {if (propertyMapping.getNestedQueryId() != null) {//关联查询// 执行另外一个select查询,把查询结果赋值给属性值,比如Student对象的teacher属性return getNestedQueryMappingValue(rs, metaResultObject, propertyMapping, lazyLoader, columnPrefix);} else if (propertyMapping.getResultSet() != null) {addPendingChildRelation(rs, metaResultObject, propertyMapping);   // TODO is that OK?return DEFERED;} else {final TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);return typeHandler.getResult(rs, column);}}//创建结果对象private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {this.useConstructorMappings = false; // reset previous mapping resultfinal List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();final List<Object> constructorArgs = new ArrayList<Object>();//结果对象Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {//获取配置的resultMap的字段与表中数据的映射关系final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();for (ResultMapping propertyMapping : propertyMappings) {// issue gcode #109 && issue #149if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);break;}}}this.useConstructorMappings = resultObject != null && !constructorArgTypes.isEmpty(); // set current mapping resultreturn resultObject;}//得到嵌套查询值private Object getNestedQueryMappingValue(ResultSet rs, MetaObject metaResultObject, ResultMapping propertyMapping, ResultLoaderMap lazyLoader, String columnPrefix)throws SQLException {final String nestedQueryId = propertyMapping.getNestedQueryId();final String property = propertyMapping.getProperty();final MappedStatement nestedQuery = configuration.getMappedStatement(nestedQueryId);final Class<?> nestedQueryParameterType = nestedQuery.getParameterMap().getType();final Object nestedQueryParameterObject = prepareParameterForNestedQuery(rs, propertyMapping, nestedQueryParameterType, columnPrefix);Object value = null;if (nestedQueryParameterObject != null) {final BoundSql nestedBoundSql = nestedQuery.getBoundSql(nestedQueryParameterObject);final CacheKey key = executor.createCacheKey(nestedQuery, nestedQueryParameterObject, RowBounds.DEFAULT, nestedBoundSql);final Class<?> targetType = propertyMapping.getJavaType();if (executor.isCached(nestedQuery, key)) {//如果已经有一级缓存了,则延迟加载(实际上deferLoad方法中可以看到则是立即加载)executor.deferLoad(nestedQuery, metaResultObject, property, key, targetType);value = DEFERED;} else {// ResultLoader保存了关联查询所需要的所有信息final ResultLoader resultLoader = new ResultLoader(configuration, executor, nestedQuery, nestedQueryParameterObject, targetType, key, nestedBoundSql);if (propertyMapping.isLazy()) {// 执行延迟加载// 语意:resultLoader的查询结果将赋值给metaResultObject源对象的property属性,resultLoader的查询参数值来自于metaResultObject源对象属性中。// 举例:查询Teacher,赋值给Student的teacher属性,参数来自于查询Student的ResultSet的teacher_id列的值。// 由于需要执行延迟加载,将查询相关信息放入缓存,但不执行查询,使用该属性时,自动触发加载操作。lazyLoader.addLoader(property, metaResultObject, resultLoader);value = DEFERED;} else {// 不执行延迟加载,立即查询并赋值value = resultLoader.loadResult();}}}return value;}//生成嵌套对象值 一对多查询private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {final DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();skipRows(rsw.getResultSet(), rowBounds);Object rowValue = previousRowValue;// 解决鉴别过的结果映射,逻辑如下:// 获取结果映射中的鉴别器,通过鉴别指定字段通过配置对象获取对应的另一个结果映射,循环往复,// 直到找不到鉴别器为止,返回最终的结果映射while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);final CacheKey rowKey = createRowKey(discriminatedResultMap, rsw, null);Object partialObject = nestedResultObjects.get(rowKey);// issue #577 && #542if (mappedStatement.isResultOrdered()) {if (partialObject == null && rowValue != null) {nestedResultObjects.clear();storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());}rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);} else {rowValue = getRowValue(rsw, discriminatedResultMap, rowKey, null, partialObject);if (partialObject == null) {storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());}}}if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());previousRowValue = null;} else if (rowValue != null) {previousRowValue = rowValue;}}private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, String columnPrefix, Object partialObject) throws SQLException {final String resultMapId = resultMap.getId();Object rowValue = partialObject;if (rowValue != null) {final MetaObject metaObject = configuration.newMetaObject(rowValue);putAncestor(rowValue, resultMapId);applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);ancestorObjects.remove(resultMapId);} else {final ResultLoaderMap lazyLoader = new ResultLoaderMap();rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {final MetaObject metaObject = configuration.newMetaObject(rowValue);boolean foundValues = this.useConstructorMappings;if (shouldApplyAutomaticMappings(resultMap, true)) {foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;}foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;putAncestor(rowValue, resultMapId);// 解析NestedResultMappings并封装结果,赋值给源对象的关联查询属性上foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;ancestorObjects.remove(resultMapId);foundValues = lazyLoader.size() > 0 || foundValues;rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;}if (combinedKey != CacheKey.NULL_CACHE_KEY) {nestedResultObjects.put(combinedKey, rowValue);}}return rowValue;}private boolean applyNestedResultMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String parentPrefix, CacheKey parentRowKey, boolean newObject) {boolean foundValues = false;for (ResultMapping resultMapping : resultMap.getPropertyResultMappings()) {final String nestedResultMapId = resultMapping.getNestedResultMapId();if (nestedResultMapId != null && resultMapping.getResultSet() == null) {try {final String columnPrefix = getColumnPrefix(parentPrefix, resultMapping);final ResultMap nestedResultMap = getNestedResultMap(rsw.getResultSet(), nestedResultMapId, columnPrefix);if (resultMapping.getColumnPrefix() == null) {// try to fill circular reference only when columnPrefix// is not specified for the nested result map (issue #215)Object ancestorObject = ancestorObjects.get(nestedResultMapId);if (ancestorObject != null) {if (newObject) {linkObjects(metaObject, resultMapping, ancestorObject); // issue #385}continue;}}final CacheKey rowKey = createRowKey(nestedResultMap, rsw, columnPrefix);final CacheKey combinedKey = combineKeys(rowKey, parentRowKey);Object rowValue = nestedResultObjects.get(combinedKey);boolean knownValue = rowValue != null;instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject); // mandatoryif (anyNotNullColumnHasValue(resultMapping, columnPrefix, rsw)) {rowValue = getRowValue(rsw, nestedResultMap, combinedKey, columnPrefix, rowValue);if (rowValue != null && !knownValue) {linkObjects(metaObject, resultMapping, rowValue);foundValues = true;}}} catch (SQLException e) {throw new ExecutorException("Error getting nested result map values for '" + resultMapping.getProperty() + "'.  Cause: " + e, e);}}}return foundValues;}}

 

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

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

相关文章

nssl1299-选做作业【最大流,最小割,最大子权闭合图】

正题 题目大意 有nnn个任务&#xff0c;完成需要先决条件&#xff0c;然后有完成价值。选择一些任务完成&#xff0c;求最大价值。 解题思路 首先&#xff0c;如果有环&#xff0c;那么这些环是不可能完成的。所以先用拓扑排序找环。 然后考虑最大子权闭合图&#xff0c;对于…

IIS中的 Asp.Net Core 和 dotnet watch

在基于传统的.NET Framework的Asp.Net Mvc的时候&#xff0c;本地开发环境中可以在IIS中建立一个站点&#xff0c;可以直接把站点的目录指向asp.net mvc的项目的根目录。然后build一下就可以在浏览器里面刷新到最新的修改了&#xff0c;也可以附加到w3wp的进程进行调试。但是在…

mybatis源码阅读(八) ---Interceptor了解一下

转载自 mybatis源码阅读(八) ---Interceptor了解一下 1 Intercetor MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下&#xff0c;MyBatis允许使用插件来拦截的方法调用包括&#xff1a; Executor (update, query, flushStatements, commit, rollba…

foreach方法使用

用法 foreach方法主要是针对数组而言的&#xff0c;对数组中的每个元素可以执行一次方法 var array [a, b, c, e]; array.forEach((a)> {console.log(a); });属性 foreach方法主要有三个参数&#xff0c;分别是数组内容、数组索引、整个数组 var array [a, b, c, e]; arra…

ssl提高组周六模拟赛【2019.3.2】

前言 Rank1Rank1Rank1耶 成绩 RankRankRank是有算别人的 只放前Rank10Rank10Rank10 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCCDDD111meselfmeselfmeself340340340808080100100100100100100606060222XXYXXYXXY250250250808080707070100100100000333LWLWLW2502502…

.NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions

.NET Core 控制台程序没有 ASP.NET Core 的 IWebHostBuilder 与 Startup.cs &#xff0c;那要读 appsettings.json、注依赖、配日志、设 IOptions 该怎么办呢&#xff1f;因为这些操作与 ASP.NET Core 无依赖&#xff0c;所以可以自己动手&#xff0c;轻松搞定。 1、读 appsett…

Object.keys方法拿到对象的key值

项目中的高级搜索选项用到了Object.keys方法&#xff0c; 那么它是用来干嘛的呢&#xff1a;删除某个子对象里的数据 var anObj { aaa: kejin,bbb: shenxian,ccc: yuanshan };let params {...anObj,ddd: luanwu } console.log(params) console.log(Object.keys(anObj)); // …

jsdiff 比较文本内容差异

翻译自 jsdiff JavaScript文本内容差异实现。 基于"An O(ND) Difference Algorithm and its Variations" (Myers, 1986) 中提出的算法 。 安装 npm install diff --save API Diff.diffChars(oldStr, newStr[, options]) -区分两个文本块&#xff0c;逐字符比较。…

Net Core下多种ORM框架特性及性能对比

在.NET Framework下有许多ORM框架&#xff0c;最著名的无外乎是Entity Framework&#xff0c;它拥有悠久的历史以及便捷的语法&#xff0c;在占有率上一路领先。但随着Dapper的出现&#xff0c;它的地位受到了威胁&#xff0c;本文对比了在.NET Core下 两种框架的表现以及与原生…

P3275-[SCOI2011]糖果【差分约束,负环】

正题 题目大意:https://www.luogu.org/problemnew/show/P3275 题目大意 对于nnn个值&#xff0c;给出一系列不等式。求每个值的最小正整数。 解题思路 差分约束 codecodecode #include<cstdio> #include<queue> #include<cstring> #define MN 300005 usi…

ssh免密登陆失败原因总结(Linux)

转载自 ssh免密登陆失败原因总结&#xff08;Linux&#xff09; 1. SSH公钥认证&#xff08;免密码&#xff09;配置 登录到本机服务器A&#xff0c;切换到响应的操作系统用户&#xff0c;执行命令&#xff0c;生成秘钥文件【按照提示直接回车】 ssh-keygen -t rsa 将公钥传送…

FormData的使用

声明 创造一个空对象 var formData new FormData();或者在里面放入一个表单 var form document.getElementById("kForm"); var formData new FormData(form);赋值 如果想在里面赋值&#xff0c;可以用append方法 添加&#xff1a; formData.append(k1,kejin)…

从ThoughtWorks 2017技术雷达看微软技术

ThoughtWorks在每年都会出品两期技术雷达&#xff0c;这是一份关于技术趋势的报告&#xff0c;它比起一些我们能在市面上见到的其他各种技术行情和预测报告&#xff0c;更加具体&#xff0c;更具可操作性&#xff0c;因为它不仅涉及到新技术大趋势&#xff0c;比如云平台和大数…

Spark入门(一)单主standalone安装

一、集群安装条件前置 实验spark安装在【Hadoop入门&#xff08;二&#xff09;集群安装】机器上&#xff0c; 已完成安装jdk,hadoop和ssh、网络等配置环境等。 spark所依赖的虚拟机和操作系统配置 环境&#xff1a;ubuntu14 spark-2.4.4-bin-hadoop2.6jdk1.8ssh 虚拟机&a…

POJ1201-Intervals【差分约束,负环,SPFA】

正题 题目链接:http://poj.org/problem?id1201 题目大意 求一个最少数量的数字集合满足 在li∼ril_i\sim r_ili​∼ri​的范围的数字至少是cic_ici​个 解题思路 设sis_isi​表示0∼i0\sim i0∼i的范围内数字个数。然后其实条件就是sr−si≥cs_r-s_i\geq csr​−si​≥c。…

laravel使用migrate操作数据库迁移

数据库表单预创建 1、生成php文件 php artisan make:migration create_articles_table2、执行php文件操作数据库 php artisan migrate --force回滚上一个 php artisan migrate:rollback回滚初始状态 php artisan migrate:reset$table->increments(id); $table->strin…

AutoMapper在asp.netcore中的使用

automapper 是.net 项目中针对模型之间转换映射的一个很好用的工具&#xff0c;不仅提高了开发的效率还使代码更加简洁&#xff0c;当然也是开源的&#xff0c;https://github.com/AutoMapper&#xff0c;这不多做介绍&#xff0c;详细看&#xff0c;官网下面是介绍它在 .net c…

Hadoop生态Zookeeper安装

一、安装条件前置 实验zookeeper安装在【Hadoop入门&#xff08;二&#xff09;集群安装】机器上&#xff0c;已完成安装jdk,hadoop和ssh配置环境等。 zookeeper所依赖的虚拟机和操作系统配置 环境&#xff1a;ubuntu14 apache-zookeeper-3.5.6-bin.tar jdk1.8ssh 虚拟机…

jzoj3054-祖孙询问【LCA】

正题 题目大意 求两个点的祖孙关系。 解题思路 直接LCALCALCA&#xff0c;然后暴力判断。 codecodecode #include<cstdio> #include<algorithm> #include<queue> #include<cmath> #define N 41000 using namespace std; struct line{int to,next,w;…

入职、最近两个月以及感悟反省

六月份我入职了 现在是八月份&#xff0c;来讲讲我获得了什么吧。 可能最重要的就是熟练了公司的环境&#xff01;熟悉了那种工作氛围&#xff01;为以后工作铺垫基础。 这个倒是必然的&#xff0c;更多的是我想知道我实际意外所获得的东西&#xff0c;下面就来讲讲吧&#xff…