MyBatis工作原理

本文转载自:https://blog.csdn.net/u014297148/article/details/78696096

1、MyBatis的架构

MyBatis的架构分层

MyBatis架构分层

MyBatis的实现原理

mybatis底层还是采用原生jdbc来对数据库进行操作的,只是通过 SqlSessionFactory,SqlSession Executor,StatementHandler,ParameterHandler,ResultHandler和TypeHandler等几个处理器封装了这些过程。

1、执行器:Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed);

2、参数处理器: ParameterHandler (getParameterObject, setParameters);

3、结构处理器: ResultSetHandler (handleResultSets, handleOutputParameters);

4、sql查询处理器:StatementHandler (prepare, parameterize, batch, update, query)

其中StatementHandler通过ParameterHandler与ResultHandler分别进行参数预编译与结果处理。而ParameterHandler与ResultHandler都使用TypeHandler进行映射。如下图: 

 2、MyBatis工作过程

首先在MyBatis启动的时候会去解析配置文件,包括全局配置文件和映射器配置文件,这里面包含了我们怎么控制MyBatis的行为,和我们要对数据库下达的指令,也就是我们的sql信息,我们会把它解析成一个Configuration对象。

接下来就是我们操作数据库的接口,它在应用程序和数据库中间,代表我们跟数据库之间的一次连接:这个就是SqlSession对象。

我们要获得一个会话,必须有一个会话工厂SqlSessionFactory,SqlSessionFactory里面又必须包含我们的所有的配置信息,所以我们会通过一个Builder来创建工厂类。

我们知道,Mybatis是对JDBC的封装,也就是意味着底层一定会出现JDBC的一些核心对象,比如执行SQL的Statement,结果集ResultSet。在MyBatis里面,SqlSession只是提供给应用的一个接口,还不是SQL的真正的执行对象。

通过看源码可以知道,SqlSession的子类DefaultSqlSession持有了一个Executor对象,用来封装对数据库的操作。在执行器Executor执行query或者update操作的时候,我们会创建一系列的对象,来处理参数、执行SQL、处理结果集,这里我们把它简化成一个对象StatementHandler。

这个就是MyBatis的工作流程,如图:

MyBatis工作流程图

通过读mybatis的源码进行分析mybatis执行操作的整个过程,我们通过debug调试就可以知道Mybatis每一步做了什么事,我先把debug每一步结果截图,然后再分析这个流程。

第一步:读取配置文件,形成InputStream。

 2.1、创建SqlSessionFactory的过程

从debug调试可以看出,返回的SqlSessionFactory是DefaultSqlSessionFactory类型的,但是Configuration此时已经被初始化了。查看源码后画下创建DefaultSqlSessionFactory的时序图:

2.2、创建SqlSession的过程

从debug调试看出,SqlSessionFactory.openSession()返回的SqlSession是DefaultSqlSession类型的,此SqlSession里包含一个Configuration对象和一个Executor对象。查看源码后画下创建DefaultSqlSession的时序图:

2.3、创建Mapper的过程

从debug调试可以看出,mapper是一个Mapper代理对象,而且初始化了Configuration对象、Executor对象。查看源码后画下创建Mapper的时序图:

2.4、执行CRUD过程

2.4.1、以select为例查看各步执行的源码

1、mapper.selectEmployeeList()其实是MapperProxy执行invoke方法,此方法先是判断Method的方法是不是Object的toString()等方法,如果不是就执行MapperMethod

 1 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 2     try {
 3         // 判断Method的方法是不是Object的toString等方法
 4         if (Object.class.equals(method.getDeclaringClass())) {
 5             return method.invoke(this, args);
 6         } else if (isDefaultMethod(method)) {
 7             return invokeDefaultMethod(proxy, method, args);
 8         }
 9     } catch (Throwable t) {
10         throw ExceptionUtil.unwrapThrowable(t);
11     }
12     // 判断private final Map<Method, MapperMethod> methodCache;这个map里面有没有这个方法的一级缓存
13     final MapperMethod mapperMethod = cachedMapperMethod(method);
14     return mapperMethod.execute(sqlSession, args);
15  }
16  
17 private MapperMethod cachedMapperMethod(Method method) {
18     MapperMethod mapperMethod = methodCache.get(method);
19     if (mapperMethod == null) {
20       mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
21       methodCache.put(method, mapperMethod);
22     }
23     return mapperMethod;
24 }

 经过上面的调用后进入MapperMethod里面执行

 1 //判断sql命令类型
 2 public Object execute(SqlSession sqlSession, Object[] args) {
 3     Object param;
 4     Object result;
 5     if(SqlCommandType.INSERT == this.command.getType()) {
 6         param = this.method.convertArgsToSqlCommandParam(args);
 7         result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
 8     } else if(SqlCommandType.UPDATE == this.command.getType()) {
 9         param = this.method.convertArgsToSqlCommandParam(args);
10         result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
11     } else if(SqlCommandType.DELETE == this.command.getType()) {
12         param = this.method.convertArgsToSqlCommandParam(args);
13         result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
14     } else if(SqlCommandType.SELECT == this.command.getType()) {
15     //我们测试的是select类型,则再判断这个方法的返回类型
16         if(this.method.returnsVoid() && this.method.hasResultHandler()) {
17             this.executeWithResultHandler(sqlSession, args);
18             result = null;
19         } else if(this.method.returnsMany()) {
20            //我们是查询列表,此方法执行
21             result = this.executeForMany(sqlSession, args);
22         } else if(this.method.returnsMap()) {
23             result = this.executeForMap(sqlSession, args);
24         } else {
25             param = this.method.convertArgsToSqlCommandParam(args);
26             result = sqlSession.selectOne(this.command.getName(), param);
27         }
28     } else {
29         if(SqlCommandType.FLUSH != this.command.getType()) {
30             throw new BindingException("Unknown execution method for: " + this.command.getName());
31         }
32         result = sqlSession.flushStatements();
33     }
34     if(result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
35         throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
36     } else {
37         return result;
38     }
39 }
40 
41 private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
42     //将param做处理 自动处理为param1,param2..
43     Object param = this.method.convertArgsToSqlCommandParam(args);
44     List result;
45     if(this.method.hasRowBounds()) {
46         RowBounds rowBounds = this.method.extractRowBounds(args);
47         //调用该对象的DefaultSqlSession的selectList方法
48         result = sqlSession.selectList(this.command.getName(), param, rowBounds);
49     } else {
50         result = sqlSession.selectList(this.command.getName(), param);
51     }
52     return !this.method.getReturnType().isAssignableFrom(result.getClass())?(this.method.getReturnType().isArray()?this.convertToArray(result):this.convertToDeclaredCollection(sqlSession.getConfiguration(), result)):result;
53 }
54 
55 //处理参数方法
56  public Object convertArgsToSqlCommandParam(Object[] args) {
57     int paramCount = this.params.size();
58     if(args != null && paramCount != 0) {
59         if(!this.hasNamedParameters && paramCount == 1) {
60             return args[((Integer)this.params.keySet().iterator().next()).intValue()];
61         } else {
62             Map<String, Object> param = new MapperMethod.ParamMap();
63             int i = 0;
64             for(Iterator i$ = this.params.entrySet().iterator(); i$.hasNext(); ++i) {
65                 Entry<Integer, String> entry = (Entry)i$.next();
66                 param.put(entry.getValue(), args[((Integer)entry.getKey()).intValue()]);
67                 String genericParamName = "param" + String.valueOf(i + 1);
68                 if(!param.containsKey(genericParamName)) {
69                     param.put(genericParamName, args[((Integer)entry.getKey()).intValue()]);
70                 }
71             }
72             return param;
73         }
74     } else {
75         return null;
76     }
77 }

 调用DefaultSqlSession的selectList()方法

 1 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
 2     List var5;
 3     try {
 4         //获取MappedStatement对象
 5         MappedStatement ms = this.configuration.getMappedStatement(statement);
 6         //调用cachingExecutor执行器的方法
 7         var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
 8     } catch (Exception var9) {
 9         throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var9, var9);
10     } finally {
11         ErrorContext.instance().reset();
12     }
13     return var5;
14 }
15 
16 //CachingExector的query方法
17 public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
18     BoundSql boundSql = ms.getBoundSql(parameterObject);
19     CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);
20     return this.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
21 }
22 
23  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
24     Cache cache = ms.getCache();
25     if(cache != null) {
26         this.flushCacheIfRequired(ms);
27         if(ms.isUseCache() && resultHandler == null) {
28             this.ensureNoOutParams(ms, parameterObject, boundSql);
29             List<E> list = (List)this.tcm.getObject(cache, key);
30             if(list == null) {
31                 //这里是调用Executor里的query方法 如果开启了缓存这掉CachingExecutor的 如果没有则是调用BaseExecutor的
32                 list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
33                 this.tcm.putObject(cache, key, list);
34             }
35 
36             return list;
37         }
38     }
39     return this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
40 }

 BaseExecutor的query方法

 1 public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
 2     BoundSql boundSql = ms.getBoundSql(parameter);
 3     CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
 4     return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
 5 }
 6 
 7 public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
 8     ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
 9     if (closed) {
10         throw new ExecutorException("Executor was closed.");
11     }
12     if (queryStack == 0 && ms.isFlushCacheRequired()) {
13         clearLocalCache();
14     }
15     List<E> list;
16     try {
17         queryStack++;
18         list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
19         if (list != null) {
20             handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
21         } else {
22             list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
23         }
24     } finally {
25         queryStack--;
26     }
27     if (queryStack == 0) {
28         for (DeferredLoad deferredLoad : deferredLoads) {
29             deferredLoad.load();
30         }
31         // issue #601
32         deferredLoads.clear();
33         if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
34             // issue #482
35             clearLocalCache();
36         }
37     }
38     return list;
39 }
40 
41 private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
42     List<E> list;
43     localCache.putObject(key, EXECUTION_PLACEHOLDER);
44     try {
45         list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
46     } finally {
47         localCache.removeObject(key);
48     }
49     localCache.putObject(key, list);
50     if (ms.getStatementType() == StatementType.CALLABLE) {
51         localOutputParameterCache.putObject(key, parameter);
52     }
53     return list;
54 }

SimpleExecutor的doQuery()方法

 1 public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
 2     Statement stmt = null;
 3     try {
 4         Configuration configuration = ms.getConfiguration();
 5         StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
 6         stmt = prepareStatement(handler, ms.getStatementLog());
 7         return handler.<E>query(stmt, resultHandler);
 8     } finally {
 9         closeStatement(stmt);
10     }
11 }
12 
13 private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
14     Statement stmt;
15     Connection connection = getConnection(statementLog);
16     stmt = handler.prepare(connection, transaction.getTimeout());
17     handler.parameterize(stmt);
18     return stmt;
19 }

ParameterHandler参数处理器的方法

1 public interface ParameterHandler {
2     Object getParameterObject();
3     //此方法是用DefaultParameterHandler实现的
4     void setParameters(PreparedStatement var1) throws SQLException;
5 }

DefaultParameterHandler默认参数处理器的方法

public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
        for (int i = 0; i < parameterMappings.size(); i++) {
            ParameterMapping parameterMapping = parameterMappings.get(i);
            if (parameterMapping.getMode() != ParameterMode.OUT) {
                Object value;
                String propertyName = parameterMapping.getProperty();
                if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
                    value = boundSql.getAdditionalParameter(propertyName);
                } else if (parameterObject == null) {
                    value = null;
                } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                    value = parameterObject;
                } else {
                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
                    value = metaObject.getValue(propertyName);
                }
                // 这里用调用 TypeHandler类型映射处理器来映射
                TypeHandler typeHandler = parameterMapping.getTypeHandler();
                JdbcType jdbcType = parameterMapping.getJdbcType();
                if (value == null && jdbcType == null) {
                    jdbcType = configuration.getJdbcTypeForNull();
                }
                try {
                    // 类型处理器设置参数映射
                    typeHandler.setParameter(ps, i + 1, value, jdbcType);
                } catch (TypeException e) {
                    throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
                } catch (SQLException e) {
                    throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
                }
            }
        }
    }
}

 SimpleStatementHandler的query()方法:

1 public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
2     String sql = boundSql.getSql();
3     statement.execute(sql);
4     return resultSetHandler.<E>handleResultSets(statement);
5 }

 

最后一句resultSetHandler.<E>handleResultSets(statement)调用的是子类DefaultResultSetHandler的handleResultSets:

  1 public List<Object> handleResultSets(Statement stmt) throws SQLException {
  2     ErrorContext.instance().activity("handling results").object(this.mappedStatement.getId());
  3     List<Object> multipleResults = new ArrayList();
  4     int resultSetCount = 0;
  5     ResultSetWrapper rsw = this.getFirstResultSet(stmt);
  6     List<ResultMap> resultMaps = this.mappedStatement.getResultMaps();
  7     int resultMapCount = resultMaps.size();
  8     this.validateResultMapsCount(rsw, resultMapCount);
  9     while(rsw != null && resultMapCount > resultSetCount) {
 10         ResultMap resultMap = (ResultMap)resultMaps.get(resultSetCount);
 11         this.handleResultSet(rsw, resultMap, multipleResults, (ResultMapping)null);
 12         rsw = this.getNextResultSet(stmt);
 13         this.cleanUpAfterHandlingResultSet();
 14         ++resultSetCount;
 15     }
 16     String[] resultSets = this.mappedStatement.getResulSets();
 17     if(resultSets != null) {
 18         while(rsw != null && resultSetCount < resultSets.length) {
 19             ResultMapping parentMapping = (ResultMapping)this.nextResultMaps.get(resultSets[resultSetCount]);
 20             if(parentMapping != null) {
 21                 String nestedResultMapId = parentMapping.getNestedResultMapId();
 22                 ResultMap resultMap = this.configuration.getResultMap(nestedResultMapId);
 23                 this.handleResultSet(rsw, resultMap, (List)null, parentMapping);
 24             }
 25             rsw = this.getNextResultSet(stmt);
 26             this.cleanUpAfterHandlingResultSet();
 27             ++resultSetCount;
 28         }
 29     }
 30     return this.collapseSingleResultList(multipleResults);
 31 }
 32 
 33 //处理结果集
 34 private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {
 35     try {
 36         if(parentMapping != null) {
 37             this.handleRowValues(rsw, resultMap, (ResultHandler)null, RowBounds.DEFAULT, parentMapping);
 38         } else if(this.resultHandler == null) {
 39             DefaultResultHandler defaultResultHandler = new DefaultResultHandler(this.objectFactory);
 40             this.handleRowValues(rsw, resultMap, defaultResultHandler, this.rowBounds, (ResultMapping)null);
 41             multipleResults.add(defaultResultHandler.getResultList());
 42         } else {
 43             this.handleRowValues(rsw, resultMap, this.resultHandler, this.rowBounds, (ResultMapping)null);
 44         }
 45     } finally {
 46         this.closeResultSet(rsw.getResultSet());
 47     }
 48 }
 49 
 50 private void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
 51     if(resultMap.hasNestedResultMaps()) {
 52         this.ensureNoRowBounds();
 53         this.checkResultHandler();
 54         this.handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
 55     } else {
 56         this.handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
 57     }
 58 }
 59 
 60 private void handleRowValuesForNestedResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
 61     DefaultResultContext<Object> resultContext = new DefaultResultContext();
 62     this.skipRows(rsw.getResultSet(), rowBounds);
 63     Object rowValue = null;
 64     while(this.shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
 65         ResultMap discriminatedResultMap = this.resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, (String)null);
 66         CacheKey rowKey = this.createRowKey(discriminatedResultMap, rsw, (String)null);
 67         Object partialObject = this.nestedResultObjects.get(rowKey);
 68         if(this.mappedStatement.isResultOrdered()) {
 69             if(partialObject == null && rowValue != null) {
 70                 this.nestedResultObjects.clear();
 71                 this.storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
 72             }
 73             //获取行的值
 74             rowValue = this.getRowValue(rsw, discriminatedResultMap, rowKey, (String)null, partialObject);
 75         } else {
 76             rowValue = this.getRowValue(rsw, discriminatedResultMap, rowKey, (String)null, partialObject);
 77             if(partialObject == null) {
 78                 this.storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
 79             }
 80         }
 81     }
 82     if (rowValue != null && mappedStatement.isResultOrdered() && shouldProcessMoreRows(resultContext, rowBounds)) {
 83         storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
 84         previousRowValue = null;
 85     } else if (rowValue != null) {
 86         previousRowValue = rowValue;
 87     }
 88 }
 89 
 90 private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap, CacheKey combinedKey, String columnPrefix, Object partialObject) throws SQLException {
 91     final String resultMapId = resultMap.getId();
 92     Object rowValue = partialObject;
 93     if (rowValue != null) {
 94         final MetaObject metaObject = configuration.newMetaObject(rowValue);
 95         putAncestor(rowValue, resultMapId);
 96         applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, false);
 97         ancestorObjects.remove(resultMapId);
 98     } else {
 99         final ResultLoaderMap lazyLoader = new ResultLoaderMap();
100         rowValue = createResultObject(rsw, resultMap, lazyLoader, columnPrefix);
101         if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {
102             final MetaObject metaObject = configuration.newMetaObject(rowValue);
103             boolean foundValues = this.useConstructorMappings;
104             if (shouldApplyAutomaticMappings(resultMap, true)) {
105                 foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, columnPrefix) || foundValues;
106             }
107             foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, columnPrefix) || foundValues;
108             putAncestor(rowValue, resultMapId);
109             foundValues = applyNestedResultMappings(rsw, resultMap, metaObject, columnPrefix, combinedKey, true) || foundValues;
110             ancestorObjects.remove(resultMapId);
111             foundValues = lazyLoader.size() > 0 || foundValues;
112             rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;
113         }
114         if (combinedKey != CacheKey.NULL_CACHE_KEY) {
115             nestedResultObjects.put(combinedKey, rowValue);
116         }
117     }
118     return rowValue;
119 }
120 
121 private boolean shouldApplyAutomaticMappings(ResultMap resultMap, boolean isNested) {
122     return resultMap.getAutoMapping() != null?resultMap.getAutoMapping().booleanValue():(isNested?AutoMappingBehavior.FULL == this.configuration.getAutoMappingBehavior():AutoMappingBehavior.NONE != this.configuration.getAutoMappingBehavior());
123 }
124 
125 private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
126     List<DefaultResultSetHandler.UnMappedColumAutoMapping> autoMapping = this.createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);
127     boolean foundValues = false;
128     if(autoMapping.size() > 0) {
129         Iterator i$ = autoMapping.iterator();
130         while(true) {
131             //这里使用了内部类对参数和结果集进行映射
132             DefaultResultSetHandler.UnMappedColumAutoMapping mapping;
133             Object value;
134             do {
135                 if(!i$.hasNext()) {
136                     return foundValues;
137                 }
138                 mapping = (DefaultResultSetHandler.UnMappedColumAutoMapping)i$.next();
139                 value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);
140             } while(value == null && !this.configuration.isCallSettersOnNulls());
141             if(value != null || !mapping.primitive) {
142                 metaObject.setValue(mapping.property, value);
143             }
144             foundValues = true;
145         }
146     } else {
147         return foundValues;
148     }
149 }
150  private static class UnMappedColumAutoMapping {
151     private final String column;
152     private final String property;
153     private final TypeHandler<?> typeHandler;
154     private final boolean primitive;
155     //此处才类型器对结果进行映射
156     public UnMappedColumAutoMapping(String column, String property, TypeHandler<?> typeHandler, boolean primitive) {
157         this.column = column;
158         this.property = property;
159         this.typeHandler = typeHandler;
160         this.primitive = primitive;
161     }
162 }

 

 

posted @ 2019-11-12 16:41  Binger阳阳  阅读(228)  评论(0)    收藏  举报