Mybatis中selectKey源碼分析
阿新 • • 發佈:2018-04-23
場景 his sql return batis ORC 獲取 int getc
剛回答了一個問題這樣一個問題,mybatis不能正常返回主鍵增加值 下面通過源碼分析一下selectKey都具體實現;關於Mybatis 基於註解Mapper源碼分析 可以看一下具體解析過程。
@Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name);
KeyGenerator接口
/** * key生成器接口 */ public interface KeyGenerator { //在執行主SQL前執行selectKey void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter); //在主SQL執行後執行selectkey void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter); }
before具體執行時機
protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { this.configuration = mappedStatement.getConfiguration(); this.executor = executor; this.mappedStatement = mappedStatement; this.rowBounds = rowBounds; this.typeHandlerRegistry = configuration.getTypeHandlerRegistry(); this.objectFactory = configuration.getObjectFactory(); if (boundSql == null) { // issue #435, get the key before calculating the statement // //執行before generateKeys(parameterObject); boundSql = mappedStatement.getBoundSql(parameterObject); } this.boundSql = boundSql; this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql); this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql); }
protected void generateKeys(Object parameter) { KeyGenerator keyGenerator = mappedStatement.getKeyGenerator(); ErrorContext.instance().store(); keyGenerator.processBefore(executor, mappedStatement, null, parameter); ErrorContext.instance().recall(); }
@Override public void processBefore(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { //是否執行前執行,如果不是就不執行 if (executeBefore) { processGeneratedKeys(executor, ms, parameter); } }
after執行時機
@Override public void processAfter(Executor executor, MappedStatement ms, Statement stmt, Object parameter) { //如果executeBefore配置為false則執行 if (!executeBefore) { processGeneratedKeys(executor, ms, parameter); } }
具體執行源碼
private void processGeneratedKeys(Executor executor, MappedStatement ms, Object parameter) { try { //如果parameter不為null同時keyStatement不為null且keyStatement 指定了keyProperties if (parameter != null && keyStatement != null && keyStatement.getKeyProperties() != null) { //獲取keyProperties String[] keyProperties = keyStatement.getKeyProperties(); //獲取配置信息 final Configuration configuration = ms.getConfiguration(); //獲取參數對象元數據 final MetaObject metaParam = configuration.newMetaObject(parameter); //其實已經判斷過了 if (keyProperties != null) { //新建keyExecutor Executor keyExecutor = configuration.newExecutor(executor.getTransaction(), ExecutorType.SIMPLE); //執行查詢 List<Object> values = keyExecutor.query(keyStatement, parameter, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER); //如果查詢結果為0個則拋出異常 if (values.size() == 0) { throw new ExecutorException("SelectKey returned no data."); } else if (values.size() > 1) {//查詢的結果個數多余1個則拋出異常 throw new ExecutorException("SelectKey returned more than one value."); } else {//只返了一個結果值 MetaObject metaResult = configuration.newMetaObject(values.get(0)); //如果keyProperty個數只有1個 if (keyProperties.length == 1) { //如果查詢結果對象存在這個屬性的getter方法 if (metaResult.hasGetter(keyProperties[0])) { //將屬性值設置到param中 setValue(metaParam, keyProperties[0], metaResult.getValue(keyProperties[0])); } else { //如果沒有getter方法就將當前值設置到屬性中 setValue(metaParam, keyProperties[0], values.get(0)); } } else {//處理指定多個key屬性場景 handleMultipleProperties(keyProperties, metaParam, metaResult); } } } } } catch (ExecutorException e) { throw e; } catch (Exception e) { throw new ExecutorException("Error selecting key or setting result to parameter object. Cause: " + e, e); } } private void handleMultipleProperties(String[] keyProperties, MetaObject metaParam, MetaObject metaResult) { //獲取所有key column String[] keyColumns = keyStatement.getKeyColumns(); //如果key column不存在 if (keyColumns == null || keyColumns.length == 0) { //沒有指定key column則直接使用配置到 key property for (String keyProperty : keyProperties) { setValue(metaParam, keyProperty, metaResult.getValue(keyProperty)); } } else { //存在key column 但是數量不一致 if (keyColumns.length != keyProperties.length) { throw new ExecutorException("If SelectKey has key columns, the number must match the number of key properties."); } //數量一致,要求keyColumn 和keyProperty一一對應 for (int i = 0; i < keyProperties.length; i++) { setValue(metaParam, keyProperties[i], metaResult.getValue(keyColumns[i])); } } }
Mybatis中selectKey源碼分析