添加mybatis-config.xml全局配置文件html
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 引入外部資源配置文件 --> <properties resource="jdbc.properties"/> <settings> <!-- 開啓駝峯自動映射 --> <setting name="mapUnderscoreToCamelCase" value="true"/> <!-- 設置二級緩存開關 默認開啓 --> <setting name="cacheEnabled" value="true"/> <!-- 延遲加載的開關 默認關閉--> <setting name="lazyLoadingEnabled" value="true"/> <!-- true啓用時,當延遲加載開啓時訪問對象中一個懶對象屬性時,將徹底加載這個對象的全部懶對象屬性。 false,當延遲加載時,按需加載對象屬性(即訪問對象中一個懶對象屬性,不會加載對象中其餘的懶對象屬性)。 默認爲false --> <setting name="aggressiveLazyLoading" value="false"/> </settings> <typeAliases> <!-- 別名 type 指定java對象類型 alias 別名名稱 --> <typeAlias type="com.laravelshao.learning.mybatis.pojo.User" alias="User"/> <!-- 指定掃描包 Mybatis會將該包下全部類都生成別名(別名首字母不區分大小寫) --> <package name="com.laravelshao.learning.mybatis.pojo"/> </typeAliases> <!-- 配置分頁插件 --> <plugins> <plugin interceptor="com.github.pagehelper.PageHelper"> <property name="dialect" value="mysql"/> <!-- 使用RowBounds分頁是否進行count查詢 默認false--> <property name="rowBoundsWithCount" value="true"/> </plugin> </plugins> <!-- 配置環境 指定數據庫鏈接信息 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <!-- 引入mapper配置文件 --> <!--<mapper resource="com/laravelshao/learning/mybatis/mapper/UserMapper.xml"/>--> <!-- 配置mapper接口掃描包 --> <package name="com.laravelshao.learning.mybatis.mapper"/> </mappers> </configuration>
jdbc.propertiesjava
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatis?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true jdbc.username=root jdbc.password=123456
添加實體類mysql
public class User implements Serializable { private Long id; // 用戶名 private String userName; // 密碼 private String password; // 姓名 private String name; // 年齡 private Integer age; // 性別 1 男性 2 女性 private Integer sex; // 出生日期 private Date birthday; // 建立時間 private Date created; // 更新時間 private Date updated; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Integer getSex() { return sex; } public void setSex(Integer sex) { this.sex = sex; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Date getCreated() { return created; } public void setCreated(Date created) { this.created = created; } public Date getUpdated() { return updated; } public void setUpdated(Date updated) { this.updated = updated; } @Override public String toString() { return "User [id=" + id + ", userName=" + userName + ", password=" + password + ", name=" + name + ", age=" + age + ", sex=" + sex + ", birthday=" + birthday + ", created=" + created + ", updated=" + updated + "]"; } }
添加mapper接口laravel
public interface UserMapper { /** * 根據id查詢用戶信息 * * @param id * @return */ User queryUserById(Long id); /** * 查詢全部用戶數據 * * @return */ List<User> queryAll(); /** * 新增用戶信息 * * @param user */ void saveUser(User user); /** * 更新用戶信息 * * @param user */ void updateUser(User user); /** * 根據id刪除用戶信息 * * @param id */ void deleteUserById(Long id); }
添加mapper映射文件git
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace 命名空間(保持惟一) 如需mybatis生成mapper動態代理類 則必須使用mapper接口全路徑 --> <mapper namespace="com.laravelshao.learning.mybatis.mapper.UserMapper"> <!-- id:ResultMap惟一標識 type:結果集映射的java對象全路徑或者別名 autoMapping:是否自動映射沒有映射關係的屬性和字段 默認開啓 --> <resultMap id="userResultMap" type="User" autoMapping="true"> <!-- column:字段名 property:屬性名 --> <id column="id" property="id"/> <result column="user_name" property="userName"/> </resultMap> <!-- 根據id查詢用戶信息 --> <!--<select id="queryUserById" resultType="User">--> <select id="queryUserById" resultMap="userResultMap"> SELECT * FROM tb_user WHERE id = #{id} </select> <!-- 查詢全部用戶數據 --> <select id="queryAll" resultType="com.laravelshao.learning.mybatis.pojo.User"> SELECT * FROM tb_user </select> <!-- 新增用戶信息 --> <insert id="saveUser" parameterType="com.laravelshao.learning.mybatis.pojo.User"> INSERT INTO tb_user ( id, user_name, password, name, age, sex, birthday, created, updated ) VALUES ( NULL, #{userName}, #{password}, #{name}, #{age}, #{sex}, #{birthday}, NOW(), NOW() ); </insert> <!-- 更新用戶信息 --> <update id="updateUser" parameterType="com.laravelshao.learning.mybatis.pojo.User"> UPDATE tb_user SET user_name = #{userName}, password = #{password}, name = #{name}, age = #{age}, sex = #{sex}, birthday = #{birthday}, updated = NOW() WHERE id = #{id} </update> <!-- 根據id刪除用戶信息 --> <delete id="deleteUserById" parameterType="java.lang.Long"> DELETE FROM tb_user WHERE id = #{id} </delete> </mapper>
添加測試方法github
public class UserMapperTest { private UserMapper userMapper; SqlSession sqlSession = null; SqlSessionFactory sqlSessionFactory = null; @Before public void setUp() throws Exception { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //openSession(boolean autoCommit) 設置事務是否自動提交 sqlSession = sqlSessionFactory.openSession(true); // 獲取動態代理實現類 this.userMapper = sqlSession.getMapper(UserMapper.class); } @Test public void testQueryUserById() { User user = userMapper.queryUserById(1L); System.out.println(user); } @Test public void testQueryAll() { List<User> users = userMapper.queryAll(); for (User user : users) { System.out.println(user); } } @Test public void testSaveUser() { User user = new User(); user.setAge(20); user.setBirthday(new Date()); user.setName("test_name_1"); user.setPassword("123456"); user.setSex(1); user.setUserName("test_userName_1"); userMapper.saveUser(user); } @Test public void testUpdateUser() { User user = userMapper.queryUserById(2L); user.setAge(30); userMapper.updateUser(user); } @Test public void testDeleteUserById() { userMapper.deleteUserById(8L); } }
SqlSession建立經過調用DefaultSqlSessionFactory的openSession方法進而調用openSessionFromDataSource方法sql
// DefaultSqlSessionFactory private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; DefaultSqlSession var8; try { Environment environment = this.configuration.getEnvironment(); // 從全局配置類configuration獲取environment信息 TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment); // 獲取事務工廠 // 建立新的事務 // 參數1:數據源 參數2:事務隔離級別 參數3:是否自動提交事務 tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); Executor executor = this.configuration.newExecutor(tx, execType); // 建立執行器 var8 = new DefaultSqlSession(this.configuration, executor, autoCommit); } catch (Exception var12) { this.closeTransaction(tx); throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12); } finally { ErrorContext.instance().reset(); } return var8; }
建立執行器數據庫
// Configuration public Executor newExecutor(Transaction transaction, ExecutorType executorType) { executorType = executorType == null ? this.defaultExecutorType : executorType; executorType = executorType == null ? ExecutorType.SIMPLE : executorType; Object executor; // 根據執行器類型建立不一樣執行器 if (ExecutorType.BATCH == executorType) { executor = new BatchExecutor(this, transaction); } else if (ExecutorType.REUSE == executorType) { executor = new ReuseExecutor(this, transaction); } else { executor = new SimpleExecutor(this, transaction); } if (this.cacheEnabled) { executor = new CachingExecutor((Executor)executor); } Executor executor = (Executor)this.interceptorChain.pluginAll(executor); return executor; }
摘自mybatis官網緩存
ExecutorType枚舉類型定義了三個值:session
• ExecutorType.SIMPLE:這個執行器類型不作特殊的事情。它爲每一個語句的執行建立一個新的預處理語句。
• ExecutorType.REUSE:這個執行器類型會複用預處理語句。
• ExecutorType.BATCH:這個執行器會批量執行全部更新語句,若是SELECT在它們中間執行,必要時請把它們區分開來以保證行爲的易讀性。
Executor定義了具體執行SQL方法
public interface Executor { ResultHandler NO_RESULT_HANDLER = null; int update(MappedStatement var1, Object var2) throws SQLException; <E> List<E> query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4, CacheKey var5, BoundSql var6) throws SQLException; <E> List<E> query(MappedStatement var1, Object var2, RowBounds var3, ResultHandler var4) throws SQLException; <E> Cursor<E> queryCursor(MappedStatement var1, Object var2, RowBounds var3) throws SQLException; List<BatchResult> flushStatements() throws SQLException; void commit(boolean var1) throws SQLException; void rollback(boolean var1) throws SQLException; CacheKey createCacheKey(MappedStatement var1, Object var2, RowBounds var3, BoundSql var4); boolean isCached(MappedStatement var1, CacheKey var2); void clearLocalCache(); void deferLoad(MappedStatement var1, MetaObject var2, String var3, CacheKey var4, Class<?> var5); Transaction getTransaction(); void close(boolean var1); boolean isClosed(); void setExecutorWrapper(Executor var1); }
調用DefaultSqlSession的getMapper方法,進而調用MapperRegistry,最後調用MapperProxyFactory最終建立出mapper代理對象
// DefaultSqlSession public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); }
// Configuration public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); }
// MapperRegistry public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession); // 交給mapper代理工廠建立對象 } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } }
Mapper代理工廠建立代理類對象
// MapperProxyFactory public T newInstance(SqlSession sqlSession) { MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); } protected T newInstance(MapperProxy<T> mapperProxy) { // JDK動態代理生成mapper代理類對象 return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); }
這裏以方法queryAll爲例分析SQL執行過程
@Test public void testQueryAll() { List<User> users = userMapper.queryAll(); for (User user : users) { System.out.println(user); } }
調用代理類的invoke方法
// MapperProxy public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } if (this.isDefaultMethod(method)) { return this.invokeDefaultMethod(proxy, method, args); } } catch (Throwable var5) { throw ExceptionUtil.unwrapThrowable(var5); } MapperMethod mapperMethod = this.cachedMapperMethod(method); return mapperMethod.execute(this.sqlSession, args); // 執行mapper方法 }
執行具體方法
// MapperMethod public Object execute(SqlSession sqlSession, Object[] args) { Object param; Object result; switch(this.command.getType()) { // 根據方法類型執行不一樣方法 case INSERT: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.insert(this.command.getName(), param)); break; case UPDATE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.update(this.command.getName(), param)); break; case DELETE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.delete(this.command.getName(), param)); break; case SELECT: if (this.method.returnsVoid() && this.method.hasResultHandler()) { this.executeWithResultHandler(sqlSession, args); result = null; } else if (this.method.returnsMany()) { result = this.executeForMany(sqlSession, args); } else if (this.method.returnsMap()) { result = this.executeForMap(sqlSession, args); } else if (this.method.returnsCursor()) { result = this.executeForCursor(sqlSession, args); } else { param = this.method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(this.command.getName(), param); } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + this.command.getName()); } if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) { throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ")."); } else { return result; } }
這裏,咱們查詢全部用戶,執行executeForMany方法
// MapperMethod private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { Object param = this.method.convertArgsToSqlCommandParam(args); List result; if (this.method.hasRowBounds()) { RowBounds rowBounds = this.method.extractRowBounds(args); result = sqlSession.selectList(this.command.getName(), param, rowBounds); } else { result = sqlSession.selectList(this.command.getName(), param); } if (!this.method.getReturnType().isAssignableFrom(result.getClass())) { return this.method.getReturnType().isArray() ? this.convertToArray(result) : this.convertToDeclaredCollection(sqlSession.getConfiguration(), result); } else { return result; } }
調用默認實現DefaultSqlSession的selectList方法
// DefaultSqlSession public <E> List<E> selectList(String statement, Object parameter) { return this.selectList(statement, parameter, RowBounds.DEFAULT); } public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { List var5; try { MappedStatement ms = this.configuration.getMappedStatement(statement); // 根據statement ID從configuration配置中獲取MappedStatement // 執行器執行查詢任務 var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception var9) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + var9, var9); } finally { ErrorContext.instance().reset(); } return var5; }
// BaseExecutor public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameter); // 根據參數動態組裝執行sql CacheKey key = this.createCacheKey(ms, parameter, rowBounds, boundSql); // 爲當前查詢任務建立緩存key return this.query(ms, parameter, rowBounds, resultHandler, key, boundSql); } public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId()); if (this.closed) { throw new ExecutorException("Executor was closed."); } else { if (this.queryStack == 0 && ms.isFlushCacheRequired()) { this.clearLocalCache(); } List list; try { ++this.queryStack; list = resultHandler == null ? (List)this.localCache.getObject(key) : null; if (list != null) { this.handleLocallyCachedOutputParameters(ms, key, parameter, boundSql); } else { list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql); // 從數據庫中查詢 } } finally { --this.queryStack; } if (this.queryStack == 0) { Iterator var8 = this.deferredLoads.iterator(); while(var8.hasNext()) { BaseExecutor.DeferredLoad deferredLoad = (BaseExecutor.DeferredLoad)var8.next(); deferredLoad.load(); } this.deferredLoads.clear(); if (this.configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { this.clearLocalCache(); } } return list; } } // 數據庫查詢 private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { this.localCache.putObject(key, ExecutionPlaceholder.EXECUTION_PLACEHOLDER); List list; try { list = this.doQuery(ms, parameter, rowBounds, resultHandler, boundSql); // 查詢結果 } finally { this.localCache.removeObject(key); } this.localCache.putObject(key, list); // 將結果放入緩存中 if (ms.getStatementType() == StatementType.CALLABLE) { this.localOutputParameterCache.putObject(key, parameter); } return list; }
調用SimpleExecutor的doQuery方法
// SimpleExecutor public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Statement stmt = null; List var9; try { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(this.wrapper, ms, parameter, rowBounds, resultHandler, boundSql); stmt = this.prepareStatement(handler, ms.getStatementLog()); // 準備語句 var9 = handler.query(stmt, resultHandler); } finally { this.closeStatement(stmt); } return var9; }
準備語句
// SimpleExecutor private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException { Connection connection = this.getConnection(statementLog); // 獲取一個數據庫鏈接對象 Statement stmt = handler.prepare(connection, this.transaction.getTimeout()); // 使用StatementHandler從數據庫鏈接對象中獲取Statement對象 handler.parameterize(stmt); // 設置參數 將sql語句中的佔位符替換爲具體參數 return stmt; }
調用PreparedStatementHandler最終執行sql語句
// PreparedStatementHandler public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException { PreparedStatement ps = (PreparedStatement)statement; ps.execute(); // 執行具體sql語句 return this.resultSetHandler.handleResultSets(ps); // 處理結果集 }
從上面能夠看出Executor的執行過程
處理結果集
// DefaultResultSetHandler public List<Object> handleResultSets(Statement stmt) throws SQLException { ErrorContext.instance().activity("handling results").object(this.mappedStatement.getId()); List<Object> multipleResults = new ArrayList(); int resultSetCount = 0; ResultSetWrapper rsw = this.getFirstResultSet(stmt); List<ResultMap> resultMaps = this.mappedStatement.getResultMaps(); int resultMapCount = resultMaps.size(); this.validateResultMapsCount(rsw, resultMapCount); while(rsw != null && resultMapCount > resultSetCount) { ResultMap resultMap = (ResultMap)resultMaps.get(resultSetCount); this.handleResultSet(rsw, resultMap, multipleResults, (ResultMapping)null); rsw = this.getNextResultSet(stmt); this.cleanUpAfterHandlingResultSet(); ++resultSetCount; } String[] resultSets = this.mappedStatement.getResultSets(); if (resultSets != null) { while(rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = (ResultMapping)this.nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = this.configuration.getResultMap(nestedResultMapId); this.handleResultSet(rsw, resultMap, (List)null, parentMapping); } rsw = this.getNextResultSet(stmt); this.cleanUpAfterHandlingResultSet(); ++resultSetCount; } } return this.collapseSingleResultList(multipleResults); }
整個執行過程完成。
下面再看看更新操做,以saveUser方法爲例分析更新流程(最終調用的都是update方法)
@Test public void testSaveUser() { User user = new User(); user.setAge(20); user.setBirthday(new Date()); user.setName("test_name_22"); user.setPassword("123456"); user.setSex(1); user.setUserName("test_userName_22"); userMapper.saveUser(user); }
執行insert、update、delete最後調用的都是下面update方法
// DefaultSqlSession public int update(String statement, Object parameter) { int var4; try { this.dirty = true; MappedStatement ms = this.configuration.getMappedStatement(statement); // 獲取對應的MappedStatement var4 = this.executor.update(ms, this.wrapCollection(parameter)); // 執行更新操做(包括包裝集合類型參數) } catch (Exception var8) { throw ExceptionFactory.wrapException("Error updating database. Cause: " + var8, var8); } finally { ErrorContext.instance().reset(); } return var4; }
// BaseExecutor public int update(MappedStatement ms, Object parameter) throws SQLException { ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId()); if (this.closed) { throw new ExecutorException("Executor was closed."); } else { this.clearLocalCache(); // 清除本地緩存 return this.doUpdate(ms, parameter); // 執行更新操做 } }
// SimpleExecutor public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { Statement stmt = null; int var6; try { Configuration configuration = ms.getConfiguration(); // 獲取全局配置信息configuration // 建立StatementHandler StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null); stmt = this.prepareStatement(handler, ms.getStatementLog()); // 準備Statement var6 = handler.update(stmt); // 處理更新操做 } finally { this.closeStatement(stmt); } return var6; }
最終執行update語句
// PreparedStatementHandler public int update(Statement statement) throws SQLException { PreparedStatement ps = (PreparedStatement)statement; ps.execute(); // 執行語句 int rows = ps.getUpdateCount(); // 獲取更新行數 Object parameterObject = this.boundSql.getParameterObject(); KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator(); // KeyGenerator後置處理 keyGenerator.processAfter(this.executor, this.mappedStatement, ps, parameterObject); return rows; }
這裏重點分析下使用selectKey標籤的SelectKeyGenerator實現
// SelectKeyGenerator public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { if (!this.executeBefore) { // 若是不是前置處理 this.processGeneratedKeys(executor, ms, parameter); // 處理生成的key } } private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) { try { if (parameter != null && this.keyStatement != null && this.keyStatement.getKeyProperties() != null) { String[] keyProperties = this.keyStatement.getKeyProperties(); // 獲取配置key的屬性信息 Configuration configuration = ms.getConfiguration(); // 獲取全局配置參數configuration參數 MetaObject metaParam = configuration.newMetaObject(parameter); if (keyProperties != null) { Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE); // 建立執行器 List<Object> values = keyExecutor.query(this.keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); // 執行查詢操做 if (values.size() == 0) { // 返回結果校驗 throw new ExecutorException("SelectKey returned no data."); } if (values.size() > 1) { throw new ExecutorException("SelectKey returned more than one value."); } MetaObject metaResult = configuration.newMetaObject(values.get(0)); if (keyProperties.length == 1) { // 只有一個參數屬性 if (metaResult.hasGetter(keyProperties[0])) { this.setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0])); } else { this.setValue(metaParam, keyProperties[0], values.get(0)); } } else { this.handleMultipleProperties(keyProperties, metaParam, metaResult); // 多個參數屬性 } } } } catch (ExecutorException var10) { throw var10; } catch (Exception var11) { throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + var11, var11); } } private void handleMultipleProperties(String[] keyProperties, MetaObject metaParam, MetaObject metaResult) { String[] keyColumns = this.keyStatement.getKeyColumns(); if (keyColumns != null && keyColumns.length != 0) { if (keyColumns.length != keyProperties.length) { throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties."); } for(int i = 0; i < keyProperties.length; ++i) { this.setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i])); // 若是沒有指定列表 則直接使用屬性名稱賦值 } } else { String[] var5 = keyProperties; int var6 = keyProperties.length; for(int var7 = 0; var7 < var6; ++var7) { String keyProperty = var5[var7]; this.setValue(metaParam, keyProperty, metaResult.getValue(keyProperty)); // 使用列名賦值 } } }
根據方法返回值類型將影響行數轉換爲指定類型
// MapperMethod private Object rowCountResult(int rowCount) { Object result; if (this.method.returnsVoid()) { result = null; } else if (!Integer.class.equals(this.method.getReturnType()) && !Integer.TYPE.equals(this.method.getReturnType())) { if (!Long.class.equals(this.method.getReturnType()) && !Long.TYPE.equals(this.method.getReturnType())) { if (!Boolean.class.equals(this.method.getReturnType()) && !Boolean.TYPE.equals(this.method.getReturnType())) { throw new BindingException("Mapper method '" + this.command.getName() + "' has an unsupported return type: " + this.method.getReturnType()); } result = rowCount > 0; } else { result = (long)rowCount; } } else { result = rowCount; } return result; }
更新操做流程分析完成。
https://blog.csdn.net/ashan_li/article/details/50378393
https://blog.csdn.net/luanlouis/article/details/40422941
https://blog.csdn.net/heroqiang/article/details/79121516
https://www.cnblogs.com/jeffen/p/6277696.html?utm_source=itdadao&utm_medium=referral