绮惧敖 MyBatis 婧愮爜鍒嗘瀽 - SqlSession 浼氳瘽涓?SQL 鎵ц鍏ュ彛

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了绮惧敖 MyBatis 婧愮爜鍒嗘瀽 - SqlSession 浼氳瘽涓?SQL 鎵ц鍏ュ彛相关的知识,希望对你有一定的参考价值。

鏍囩锛?a href='http://www.mamicode.com/so/1/factor' title='factor'>factor   apc   鍒ゆ柇   null   ret   catch   婧愮爜   

璇ョ郴鍒楁枃妗f槸鏈汉鍦ㄥ涔?Mybatis 鐨勬簮鐮佽繃绋嬩腑鎬荤粨涓嬫潵鐨勶紝鍙兘瀵硅鑰呬笉澶弸濂斤紝璇风粨鍚堟垜鐨勬簮鐮佹敞閲婏紙Mybatis婧愮爜鍒嗘瀽 GitHub 鍦板潃銆?a href="https://github.com/liu844869663/spring">Mybatis-Spring 婧愮爜鍒嗘瀽 GitHub 鍦板潃銆?a href="https://github.com/liu844869663/spring-boot-starter">Spring-Boot-Starter 婧愮爜鍒嗘瀽 GitHub 鍦板潃锛夎繘琛岄槄璇?/p>

MyBatis 鐗堟湰锛?.5.2

MyBatis-Spring 鐗堟湰锛?.0.3

MyBatis-Spring-Boot-Starter 鐗堟湰锛?.1.4

SqlSession浼氳瘽涓嶴QL鎵ц鍏ュ彛

鍦ㄥ墠闈竴绯诲垪鐨勬枃妗d腑锛屽凡缁忚缁嗙殑浠嬬粛浜?MyBatis 鐨勫垵濮嬪寲鍜屾墽琛?SQL 鐨勮繃绋嬶紝鍦ㄦ墽琛?SQL 鐨勮繃绋嬩腑锛岃繕瀛樺湪鐫€涓€浜涚枒闂紝渚嬪鍏朵腑涓€鐩存彁鍒扮殑 SqlSession 浼氳瘽鍦?MyBatis 涓槸濡備綍琚垱寤虹殑锛熷浣曡皟鐢?Executor 鎵ц鍣ㄦ墽琛?SQL 鐨勶紵

閭d箞鎺ヤ笅鏉ュ氨鍏充簬涓婇潰涓や釜鐨勪袱涓棶棰橈紝涓€璧锋潵鎺㈣涓€涓?MyBatis 涓?SqlSession 浼氳瘽鐨勭浉鍏冲唴瀹?/p>

鍏堝洖椤句竴涓?a href="https://www.cnblogs.com/lifullmoon/p/14014934.html">銆婂熀纭€鏀寔灞傘€?/strong>鐨?strong>Binding妯″潡锛屾瘡涓?code>Mapper Interface浼氭湁瀵瑰簲鐨?code>MapperProxyFactory鍔ㄦ€佷唬鐞嗗璞″伐鍘傦紝鐢ㄤ簬鍒涘缓MapperProxy鍔ㄦ€佷唬鐞嗗璞★紝Mapper 鎺ュ彛涓殑姣忎釜鏂规硶閮芥湁瀵瑰簲鐨?code>MapperMethod瀵硅薄锛岃瀵硅薄浼氶€氳繃 SqlSession 浼氳瘽鎵ц鏁版嵁鎿嶄綔

鍐嶆潵鐪嬪埌杩欏紶MyBatis鏁翠綋鍥撅細

鎶€鏈浘鐗? src=

鍦ㄥ崟鐙娇鐢?MyBatis 杩涜鏁版嵁搴撴搷浣滄椂锛岄渶瑕侀€氳繃SqlSessionFactoryBuilder鏋勫缓涓€涓?code>SessionFactory瀵硅薄锛岀劧鍚庨€氳繃瀹冨垱寤轰竴涓?code>SqlSession浼氳瘽杩涜鏁版嵁搴撴搷浣?/p>

鎴戜滑閫氬父閮戒細鍏堣皟鐢?code>SqlSession浼氳瘽鐨?code>getMapper(Class<T> mapper)鏂规硶锛屼负 Mapper 鎺ュ彛鐢熸垚涓€涓€滃疄鐜扮被鈥濓紙JDK鍔ㄦ€佷唬鐞嗗璞★級锛岀劧鍚庡氨鍙互閫氳繃瀹冭繘琛屾暟鎹簱鎿嶄綔

绀轰緥

// <1> 鏋勫缓 SqlSessionFactory 瀵硅薄
Reader reader = Resources.getResourceAsReader("org/apache/ibatis/autoconstructor/mybatis-config.xml");
// <2> 榛樿 DefaultSqlSessionFactory 瀵硅薄
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

// <3> 鑾峰緱 SqlSession 瀵硅薄锛岄粯璁?DefaultSqlSession 瀵硅薄
SqlSession sqlSession = sqlSessionFactory.openSession();

// <4> 鑾峰緱 Mapper 瀵硅薄
final AutoConstructorMapper mapper = sqlSession.getMapper(AutoConstructorMapper.class);

// <5> 鎵ц鏌ヨ
final Object subject = mapper.getSubject(1);

SqlSessionFactoryBuilder

org.apache.ibatis.session.SqlSessionFactoryBuilder锛氭瀯寤篠qlSessionFactory宸ュ巶绫伙紝閲岄潰瀹氫箟浜嗚澶歜uild閲嶈浇鏂规硶锛屼富瑕佸垎涓哄鐞哛eader鍜孖nputStream涓ょ鏂囦欢璧勬簮瀵硅薄锛屼唬鐮佸涓嬶細

public class SqlSessionFactoryBuilder {

	public SqlSessionFactory build(Reader reader) {
		return build(reader, null, null);
	}

	public SqlSessionFactory build(Reader reader, String environment) {
		return build(reader, environment, null);
	}

	public SqlSessionFactory build(Reader reader, Properties properties) {
		return build(reader, null, properties);
	}

	/**
	 * 鏋勯€?SqlSessionFactory 瀵硅薄
	 *
	 * @param reader Reader 瀵硅薄
	 * @param environment 鐜
	 * @param properties Properties 鍙橀噺
	 * @return SqlSessionFactory 瀵硅薄
	 */
	public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
		try {
			/*
			 * <1> 鍒涘缓 XMLConfigBuilder 瀵硅薄
			 * 浼氱敓鎴愪竴涓?XPathParser锛屽寘鍚?Document 瀵硅薄
			 * 浼氬垱寤轰竴涓?Configuration 鍏ㄥ眬閰嶇疆瀵硅薄
			 */
			XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
			/*
			 * <2> 瑙f瀽 XML 鏂囦欢骞堕厤缃埌 Configuration 鍏ㄥ眬閰嶇疆瀵硅薄涓?			 * <3> 鍒涘缓 DefaultSqlSessionFactory 瀵硅薄
			 */
			return build(parser.parse());
		} catch (Exception e) {
			throw ExceptionFactory.wrapException("Error building SqlSession.", e);
		} finally {
			ErrorContext.instance().reset();
			try {
				reader.close();
			} catch (IOException e) {
				// Intentionally ignore. Prefer previous error.
			}
		}
	}

	public SqlSessionFactory build(InputStream inputStream) {
		return build(inputStream, null, null);
	}

	public SqlSessionFactory build(InputStream inputStream, String environment) {
		return build(inputStream, environment, null);
	}

	public SqlSessionFactory build(InputStream inputStream, Properties properties) {
		return build(inputStream, null, properties);
	}

	public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
		try {
			XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
			return build(parser.parse());
		} catch (Exception e) {
			throw ExceptionFactory.wrapException("Error building SqlSession.", e);
		} finally {
			ErrorContext.instance().reset();
			try {
				inputStream.close();
			} catch (IOException e) {
				// Intentionally ignore. Prefer previous error.
			}
		}
	}

	public SqlSessionFactory build(Configuration config) {
		return new DefaultSqlSessionFactory(config);
	}

}

鍦?a href="https://www.cnblogs.com/lifullmoon/p/14015009.html">銆奙yBatis鍒濆鍖栵紙涓€锛変箣鍔犺浇mybatis-config.xml銆?/strong>涓凡缁忓垎鏋愪簡锛岃繖閲屽氨涓嶅啀璧樿堪锛屽氨鏄牴鎹枃浠惰祫婧愬垱寤篊onfiguration鍏ㄥ眬閰嶇疆瀵硅薄锛岀劧鍚庢瀯寤轰竴涓狣efaultSqlSessionFactory瀵硅薄

DefaultSqlSessionFactory

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory锛氬疄鐜?SqlSessionFactory 鎺ュ彛锛岄粯璁ょ殑 SqlSessionFactory 瀹炵幇绫?/p>

openSession鏂规硶

openSession鏂规硶锛屽垱寤轰竴涓?code>DefaultSqlSession瀵硅薄锛屽涓嬶細

public class DefaultSqlSessionFactory implements SqlSessionFactory {

	private final Configuration configuration;

	public DefaultSqlSessionFactory(Configuration configuration) {
		this.configuration = configuration;
	}

	@Override
	public SqlSession openSession() {
		return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
	}

	@Override
	public SqlSession openSession(boolean autoCommit) {
		return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
	}

	@Override
	public SqlSession openSession(ExecutorType execType) {
		return openSessionFromDataSource(execType, null, false);
	}

	@Override
	public SqlSession openSession(TransactionIsolationLevel level) {
		return openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
	}

	@Override
	public SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level) {
		return openSessionFromDataSource(execType, level, false);
	}

	@Override
	public SqlSession openSession(ExecutorType execType, boolean autoCommit) {
		return openSessionFromDataSource(execType, null, autoCommit);
	}

	@Override
	public SqlSession openSession(Connection connection) {
		return openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
	}

	@Override
	public SqlSession openSession(ExecutorType execType, Connection connection) {
		return openSessionFromConnection(execType, connection);
	}
}

openSession鏈夊緢澶氶噸杞界殑鏂规硶锛屼富瑕佹槸鎻愪緵浠ヤ笅鍑犵鍏ュ弬鐨勬敮鎸侊細

绫诲瀷 鍙傛暟鍚嶇О 榛樿鍊?/th> 鎻忚堪
boolean autoCommit false 浜嬪姟鏄惁鑷姩鎻愪氦
ExecutorType execType ExecutorType.SIMPLE Executor鎵ц鍣ㄧ被鍨?/td>
TransactionIsolationLevel level 鏃?/td> 浜嬪姟闅旂绾у埆
java.sql.Connection connection 鏃?/td> 鏁版嵁搴撹繛鎺?/td>

鍐呴儴鐩存帴璋冪敤openSessionFromDataSource绉佹湁鏂规硶锛屽唴閮ㄤ篃闇€瑕佽皟鐢?code>openSessionFromConnection绉佹湁鏂规硶锛屽鏋滃瓨鍦?code>connection鍏ュ弬锛屽唴閮ㄥ垯鐩存帴璋冪敤openSessionFromConnection绉佹湁鏂规硶

openSessionFromDataSource鏂规硶

openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)鏂规硶锛岀敤浜庡垱寤轰竴涓?code>DefaultSqlSession瀵硅薄锛屾柟娉曞涓嬶細

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level,
        boolean autoCommit) {
    Transaction tx = null;
    try {
        // 鑾峰緱 Environment 瀵硅薄
        final Environment environment = configuration.getEnvironment();
        // 鍒涘缓 Transaction 瀵硅薄
        final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
        tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
        // 鍒涘缓 Executor 瀵硅薄
        final Executor executor = configuration.newExecutor(tx, execType);
        // 鍒涘缓 DefaultSqlSession 瀵硅薄
        return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
        // 濡傛灉鍙戠敓寮傚父锛屽垯鍏抽棴 Transaction 瀵硅薄
        closeTransaction(tx); // may have fetched a connection so lets call close()
        throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
        ErrorContext.instance().reset();
    }
}
  1. 鑾峰緱Environment褰撳墠鐜瀵硅薄
  2. 閫氳繃getTransactionFactoryFromEnvironment鏂规硶锛屼粠 Environment 鐜瀵硅薄涓?code>TransactionFactory瀵硅薄锛岀敤浜庡垱寤轰竴涓?code>Transaction浜嬪姟
  3. 鐒跺悗鍐嶅垱寤轰竴涓?code>Executor鎵ц鍣ㄥ璞?/li>
  4. 鏍规嵁鍏ㄥ眬閰嶇疆瀵硅薄銆佹墽琛屽櫒鍜屼簨鍔℃槸鍚﹁嚜鍔ㄦ彁浜ゅ垱寤轰竴涓?code>DefaultSqlSession瀵硅薄

openSessionFromConnection鏂规硶

openSessionFromConnection(ExecutorType execType, Connection connection)鏂规硶锛岀敤浜庡垱寤轰竴涓?code>DefaultSqlSession瀵硅薄

鍜屼笂闈㈢殑鏂规硶閫昏緫鐩稿悓锛屽彧涓嶈繃瀹冪殑鍏ュ弬鐩存帴浼犲叆浜嗕竴涓狢onnection鏁版嵁搴撹繛鎺ワ紝鏂规硶濡備笅锛?/p>

private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    try {
        // 鑾峰緱鏄惁鍙互鑷姩鎻愪氦
        boolean autoCommit;
        try {
            autoCommit = connection.getAutoCommit();
        } catch (SQLException e) {
            // Failover to true, as most poor drivers
            // or databases won鈥榯 support transactions
            autoCommit = true;
        }
        // 鑾峰緱 Environment 瀵硅薄
        final Environment environment = configuration.getEnvironment();
        // 鍒涘缓 Transaction 瀵硅薄
        final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
        final Transaction tx = transactionFactory.newTransaction(connection);
        // 鍒涘缓 Executor 瀵硅薄
        final Executor executor = configuration.newExecutor(tx, execType);
        // 鍒涘缓 DefaultSqlSession 瀵硅薄
        return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
        ErrorContext.instance().reset();
    }
}

鍜屼笂闈㈢殑鏂规硶涓嶅悓鐨勬槸锛屽垱寤?code>Transaction浜嬪姟瀵硅薄鏃讹紝浼犲叆鐨勫弬鏁扮洿鎺ユ槸Connection鏁版嵁搴撹繛鎺ュ璞?/p>

getTransactionFactoryFromEnvironment鏂规硶

getTransactionFactoryFromEnvironment(Environment environment)鏂规硶锛岀敤浜庡垱寤轰竴涓?code>TransactionFactory瀵硅薄锛屽湪鍒涘缓 SqlSessionFactory 鏃讹紝灏卞彲浠ラ€氳繃璁剧疆 Environment 鐨?DataSource 鏁版嵁婧愬拰 TransactionFactory 浜嬪姟宸ュ巶鏉ラ泦鎴愮涓夋柟鏁版嵁婧愬拰浜嬪姟绠$悊鍣紝浠g爜濡備笅锛?/p>

private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
    // 鎯呭喌涓€锛屽垱寤?ManagedTransactionFactory 瀵硅薄
    if (environment == null || environment.getTransactionFactory() == null) {
        return new ManagedTransactionFactory();
    }
    // 鎯呭喌浜岋紝浣跨敤 `environment` 涓殑
    return environment.getTransactionFactory();
}

closeTransaction鏂规硶

closeTransaction(Transaction tx)鏂规硶锛屽叧闂簨鍔★紝鏂规硶濡備笅锛?/p>

private void closeTransaction(Transaction tx) {
    if (tx != null) {
        try {
            tx.close();
        } catch (SQLException ignore) {
            // Intentionally ignore. Prefer previous error.
        }
    }
}

DefaultSqlSession

org.apache.ibatis.session.defaults.DefaultSqlSession锛氬疄鐜?SqlSession 鎺ュ彛锛岄粯璁ょ殑 SqlSession 瀹炵幇绫伙紝璋冪敤 Executor 鎵ц鍣紝鎵ц鏁版嵁搴撴搷浣?/p>

public class DefaultSqlSession implements SqlSession { /** * 鍏ㄥ眬閰嶇疆 */ private final Configuration configuration; /** * 鎵ц鍣ㄥ璞? */ private final Executor executor; /** * 鏄惁鑷姩鎻愪氦浜嬪姟 */ private final boolean autoCommit; /** * 鏄惁鍙戠敓鏁版嵁鍙樻洿 */ private boolean dirty; /** * Cursor 鏁扮粍 */ private List<Cursor<?>> cursorList; public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) { this.configuration = configuration; this.executor = executor; this.dirty = false; this.autoCommit = autoCommit; } }

select鏂规硶

鎵ц鏁版嵁搴撴煡璇㈡搷浣滐紝鎻愪緵浜嗚澶氶噸杞芥柟娉?/p>

@Override
public void select(String statement, Object parameter, ResultHandler handler) {
    select(statement, parameter, RowBounds.DEFAULT, handler);
}

@Override
public void select(String statement, ResultHandler handler) {
    select(statement, null, RowBounds.DEFAULT, handler);
}

@Override
public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
    try {
        MappedStatement ms = configuration.getMappedStatement(statement);
        executor.query(ms, wrapCollection(parameter), rowBounds, handler);
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
        ErrorContext.instance().reset();
    }
}

@Override
public <T> T selectOne(String statement) {
    return this.selectOne(statement, null);
}

@Override
public <T> T selectOne(String statement, Object parameter) {
    // Popular vote was to return null on 0 results and throw exception on too many.
    List<T> list = this.selectList(statement, parameter);
    if (list.size() == 1) {
        return list.get(0);
    } else if (list.size() > 1) {
        throw new TooManyResultsException(
                "Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
        return null;
    }
}

@Override
public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
    return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
}

@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
    return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
}

@Override
public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
    // <1> 鎵ц鏌ヨ
    final List<? extends V> list = selectList(statement, parameter, rowBounds);
    // <2> 鍒涘缓 DefaultMapResultHandler 瀵硅薄
    final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<>(mapKey,
            configuration.getObjectFactory(), configuration.getObjectWrapperFactory(),
            configuration.getReflectorFactory());
    // <3> 鍒涘缓 DefaultResultContext 瀵硅薄
    final DefaultResultContext<V> context = new DefaultResultContext<>();
    // <4> 閬嶅巻鏌ヨ缁撴灉
    for (V o : list) {
        // 璁剧疆 DefaultResultContext 涓?        context.nextResultObject(o);
        // 浣跨敤 DefaultMapResultHandler 澶勭悊缁撴灉鐨勫綋鍓嶅厓绱?        mapResultHandler.handleResult(context);
    }
    // <5> 杩斿洖缁撴灉
    return mapResultHandler.getMappedResults();
}

@Override
public <E> List<E> selectList(String statement) {
    return this.selectList(statement, null);
}

@Override
public <E> List<E> selectList(String statement, Object parameter) {
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
}

@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
        // <1> 鑾峰緱 MappedStatement 瀵硅薄
        MappedStatement ms = configuration.getMappedStatement(statement);
        // <2> 鎵ц鏌ヨ
        return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
        ErrorContext.instance().reset();
    }
}

涓婇潰鏈夊緢澶氱殑鏁版嵁搴撴煡璇㈡柟娉曪紝涓昏鍒嗕负浠ヤ笅鍑犵锛?/p>

  • select锛氭墽琛屾暟鎹簱鏌ヨ鎿嶄綔锛岄€氳繃鍏ュ弬涓殑ResultHandler澶勭悊缁撴灉闆嗭紝鏃犺繑鍥炵粨鏋?/li>
  • selectList锛氭墽琛屾暟鎹簱鏌ヨ鎿嶄綔锛岃繑鍥濴ist闆嗗悎
  • selectOne锛氳皟鐢?code>selectList鏂规硶锛屾墽琛屾暟鎹簱鏌ヨ鎿嶄綔锛屾渶澶氬彧鑳借繑鍥炰竴鏉℃暟鎹?/li>
  • selectMap锛氳皟鐢?code>selectList鏂规硶锛屾墽琛屾暟鎹簱鏌ヨ鎿嶄綔锛岄€氳繃DefaultMapResultHandler杩涜澶勭悊锛屽皢杩斿洖缁撴灉杞崲鎴怣ap闆嗗悎

鍙互鐪嬪埌閫氳繃Executor鎵ц鍣ㄧ殑query鏂规硶鎵ц鏌ヨ鎿嶄綔锛屽彲浠ュ洖椤?a href="https://www.cnblogs.com/lifullmoon/p/14015111.html">銆奡QL鎵ц杩囩▼锛堜竴锛変箣Executor銆?/strong>涓殑鍐呭

杩欓噷浼氬厛璋冪敤wrapCollection鏂规硶瀵瑰叆鍙傝繘琛屽寘瑁咃紙濡傛灉鏄泦鍚堢被鍨嬶級

update鏂规硶

鎵ц鏁版嵁搴撴洿鏂版搷浣?/p>

@Override
public int insert(String statement) {
    return insert(statement, null);
}

@Override
public int insert(String statement, Object parameter) {
    return update(statement, parameter);
}

@Override
public int delete(String statement) {
    return update(statement, null);
}

@Override
public int delete(String statement, Object parameter) {
    return update(statement, parameter);
}

@Override
public int update(String statement) {
    return update(statement, null);
}

@Override
public int update(String statement, Object parameter) {
    try {
        // <1> 鏍囪 dirty 锛岃〃绀烘墽琛岃繃鍐欐搷浣?        dirty = true;
        // <2> 鑾峰緱 MappedStatement 瀵硅薄
        MappedStatement ms = configuration.getMappedStatement(statement);
        // <3> 鎵ц鏇存柊鎿嶄綔
        return executor.update(ms, wrapCollection(parameter));
    } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
    } finally {
        ErrorContext.instance().reset();
    }
}

insert鍜?code>delete鏂规硶鏈€缁堥兘鏄皟鐢?code>update鏂规硶锛岄€氳繃Executor鎵ц鍣ㄧ殑update鏂规硶鎵ц鏁版嵁搴撴洿鏂版搷浣?/p>

杩欓噷浼氬厛璋冪敤wrapCollection鏂规硶瀵瑰叆鍙傝繘琛屽寘瑁咃紙濡傛灉鏄泦鍚堢被鍨嬶級

wrapCollection鏂规硶

wrapCollection(final Object object)鏂规硶锛屽皢闆嗗悎绫诲瀷鐨勫弬鏁板寘瑁呮垚StrictMap瀵硅薄锛屾柟娉曞涓嬶細

public static class StrictMap<V> extends HashMap<String, V> {

    private static final long serialVersionUID = -5741767162221585340L;

    @Override
    public V get(Object key) {
        if (!super.containsKey(key)) {
            throw new BindingException(
                    "Parameter 鈥? + key + "鈥?not found. Available parameters are " + this.keySet());
        }
        return super.get(key);
    }

}

private Object wrapCollection(final Object object) {
    if (object instanceof Collection) {
        // 濡傛灉鏄泦鍚堬紝鍒欐坊鍔犲埌 collection 涓?        StrictMap<Object> map = new StrictMap<>();
        map.put("collection", object);
        // 濡傛灉鏄?List 锛屽垯娣诲姞鍒?list 涓?        if (object instanceof List) {
            map.put("list", object);
        }
        return map;
    } else if (object != null && object.getClass().isArray()) {
        // 濡傛灉鏄?Array 锛屽垯娣诲姞鍒?array 涓?        StrictMap<Object> map = new StrictMap<>();
        map.put("array", object);
        return map;
    }
    return object;
}

getMapper鏂规硶

getMapper(Class<T> type)鏂规硶锛岃幏鍙朚apper鎺ュ彛鐨勪唬鐞嗗璞?/p>

@Override
public <T> T getMapper(Class<T> type) {
    return configuration.getMapper(type, this);
}

閫氳繃Configuration鍏ㄥ眬閰嶇疆瀵硅薄鑾峰彇涓€涓姩鎬佷唬鐞嗗璞?/p>

瀹為檯閫氳繃MapperRegistry娉ㄥ唽琛ㄨ幏鍙栧埌璇apper鎺ュ彛瀵瑰簲鐨?code>MapperProxyFactory鍔ㄦ€佷唬鐞嗗伐鍘傦紝鐒跺悗鍒涘缓涓€涓?code>MapperProxy鍔ㄦ€佷唬鐞嗙殑瀹炰緥瀵硅薄

鍏朵粬鏂规硶

  • flushStatements()锛氭彁浜ゆ壒澶勭悊
  • commit()锛氭彁浜や簨鍔?/li>
  • rollback()锛氬洖婊氫簨鍔?/li>
  • close()锛氬叧闂綋鍓嶄細璇?/li>
  • getConnection()锛氳幏鍙栧綋鍓嶄簨鍔$殑鏁版嵁搴撹繛鎺?/li>
  • clearCache()锛氭竻鐞嗕竴绾х紦瀛?/li>

MapperMethod

org.apache.ibatis.binding.MapperMethod锛歁apper鎺ュ彛涓畾涔夌殑鏂规硶瀵瑰簲鐨凪apper鏂规硶锛岄€氳繃瀹冩潵鎵цSQL

鍏堟潵鐪嬬湅鎵ц涓€涓猄QL鐨勫畬鏁存祦绋嬪浘锛?/p> 鎶€鏈浘鐗? src=

鍦?a href="https://www.cnblogs.com/lifullmoon/p/14014934.html">銆婂熀纭€鏀寔灞傘€?/strong>鐨?strong>Binding妯″潡宸茬粡璁茶繃浜嗙浉鍏崇殑鍐呭锛屼緥濡傜湅鍒板墠闈?strong>绀轰緥鐨勭4姝ワ紝閫氳繃DefaultSqlSession鐨?code>getMapper鏂规硶浼氭墽琛屼互涓嬫搷浣滐細

  1. 鍒涘缓Mapper鎺ュ彛瀵瑰簲鐨?code>MapperProxyFactory鍔ㄦ€佷唬鐞嗗璞″伐鍘?/li>
  2. 閫氳繃杩欎釜宸ュ巶鐨?code>newInstance鏂规硶浼氬垱寤轰竴涓?code>MapperProxy鎺ュ彛浠g悊绫伙紝鐒跺悗杩斿洖璇apper鎺ュ彛鐨勫姩鎬佷唬鐞嗗璞?/li>

褰撲綘璋冪敤杩欎釜鎺ュ彛鐨勬煇涓柟娉曟椂锛屼細杩涘叆杩欎釜MapperProxy浠g悊绫伙紝鎴戜滑鏉ョ湅鍒板畠鐨?code>invoke鏂规硶鏄浣曞疄鐜扮殑锛屾柟娉曞涓嬶細

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
        // <1> 濡傛灉鏄?Object 瀹氫箟鐨勬柟娉曪紝鐩存帴璋冪敤
        if (Object.class.equals(method.getDeclaringClass())) {
            return method.invoke(this, args);
        } else if (method.isDefault()) { // 鏄惁鏈?default 淇グ鐨勬柟娉?            // 閽堝Java7浠ヤ笂鐗堟湰瀵瑰姩鎬佺被鍨嬭瑷€鐨勬敮鎸?            if (privateLookupInMethod == null) {
                return invokeDefaultMethodJava8(proxy, method, args);
            } else {
                return invokeDefaultMethodJava9(proxy, method, args);
            }
        }
    } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
    }
    // <2.1> 鑾峰緱 MapperMethod 瀵硅薄
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    // <2.2> 鎵ц MapperMethod 鏂规硶
    return mapperMethod.execute(sqlSession, args);
}

棣栧厛鑾峰彇鍒版柟娉曞搴旂殑MapperMethod瀵硅薄锛岀劧鍚庨€氳繃璇ュ璞″幓鎵ц鏁版嵁搴撶殑鎿嶄綔

execute鏂规硶

public Object execute(SqlSession sqlSession, Object[] args) {
    // 鏍规嵁 SqlCommand 鐨?Type 鍒ゆ柇搴旇濡備綍鎵ц SQL 璇彞
    Object result;
    switch (command.getType()) {
    case INSERT: {
        // <1> 鑾峰彇鍙傛暟鍊间笌鍙傛暟鍚嶇殑鏄犲皠
        Object param = method.convertArgsToSqlCommandParam(args);
  		// <2> 鐒跺悗閫氳繃 SqlSession 杩涜鏁版嵁搴撴洿鏂版搷浣滐紝骞跺皢鍙楀奖鍝嶈鏁拌浆鎹负缁撴灉
        result = rowCountResult(sqlSession.insert(command.getName(), param));
        break;
    }
    case UPDATE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.update(command.getName(), param));
        break;
    }
    case DELETE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.delete(command.getName(), param));
        break;
    }
    case SELECT:
        if (method.returnsVoid() && method.hasResultHandler()) { // 鏃犺繑鍥烇紝涓斿叆鍙備腑鏈?ResultHandler 缁撴灉澶勭悊鍣?            executeWithResultHandler(sqlSession, args);
            result = null;
        } else if (method.returnsMany()) {
    		// 鎵ц鏌ヨ锛岃繑鍥炲垪琛?            result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {
    		// 鎵ц鏌ヨ锛岃繑鍥?Map
            result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) {
    		// 鎵ц鏌ヨ锛岃繑鍥?Cursor
            result = executeForCursor(sqlSession, args);
        } else { // 鎵ц鏌ヨ锛岃繑鍥炲崟涓璞?            // 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
            Object param = method.convertArgsToSqlCommandParam(args);
            // 鎵ц鏌ヨ锛岃繑鍥炲崟鏉℃暟鎹?            result = sqlSession.selectOne(command.getName(), param);
            if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) {
                result = Optional.ofNullable(result);
            }
        }
        break;
    case FLUSH:
        result = sqlSession.flushStatements();
        break;
    default:
        throw new BindingException("Unknown execution method for: " + command.getName());
    }
    // 杩斿洖缁撴灉涓?null 锛屽苟涓旇繑鍥炵被鍨嬩负鍘熷绫诲瀷锛堝熀鏈被鍨嬶級锛屽垯鎶涘嚭 BindingException 寮傚父
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
        throw new BindingException("Mapper method 鈥? + command.getName()
                + " attempted to return null from a method with a primitive return type (" + method.getReturnType()
                + ").");
    }
    return result;
}

鏍规嵁 SqlCommand 鐨?Type 鍒ゆ柇搴旇濡備綍鎵ц SQL 璇彞锛岀被鍨嬪垎涓?code>INSERT銆?code>UPDATE銆?code>DELETE銆?code>SELECT鍜?code>FLUSH锛堣繘琛屾壒澶勭悊锛変簲绉?/p>

鍓嶄笁绉嶉兘灞炰簬鏁版嵁搴撶殑鏇存柊鎿嶄綔锛岃皟鐢ㄧ殑鏄?code>DefaultSqlSession鐨?code>update鏂规硶锛岄€氳繃rowCountResult(int rowCount)灏嗗彈褰卞搷琛屾暟杞崲涓鸿繑鍥炲璞?/p>

鏌ヨ璇彞鐨勮瘽灏卞垎涓轰互涓嬪嚑绉嶆儏鍐碉細

  1. 鏃犺繑鍥烇紝涓斿叆鍙備腑鏈?ResultHandler 缁撴灉澶勭悊鍣紝鍒欒皟鐢?code>executeWithResultHandler鏂规硶锛屾墽琛屾煡璇紝杩斿洖缁撴灉璁剧疆涓簄ull
  2. 杩斿洖瀵硅薄涓哄鏉℃暟鎹紝鍒欒皟鐢?code>executeForMany鏂规硶锛屾墽琛屾煡璇紝杩斿洖鍒楄〃
  3. 杩斿洖瀵硅薄涓篗ap绫诲瀷锛屽垯璋冪敤executeForMap鏂规硶锛屾墽琛屾煡璇紝杩斿洖Map
  4. 杩斿洖瀵硅薄涓篊ursor绫诲瀷锛屽垯璋冪敤executeForCursor鏂规硶锛屾墽琛屾煡璇紝杩斿洖Cursor
  5. 杩斿洖瀵硅薄涓哄崟涓璞★紝鍒欒皟鐢?code>DefaultSqlSession鐨?code>selectOne鏂规硶锛屾墽琛屾煡璇紝杩斿洖鍗曚釜瀵硅薄

涓婇潰鎵ц鏁版嵁搴撴搷浣滃墠浼氬厛璋冪敤convertArgsToSqlCommandParam鏂规硶锛岃幏鍙栧弬鏁板€间笌鍙傛暟鍚嶇殑鏄犲皠

convertArgsToSqlCommandParam鏂规硶

convertArgsToSqlCommandParam(Object[] args)鏂规硶锛屾牴鎹叆鍙傝繑鍥炲弬鏁板悕绉颁笌鍏ュ弬鐨勬槧灏勶紝鏂规硶濡備笅锛?/p>

public Object convertArgsToSqlCommandParam(Object[] args) {
    return paramNameResolver.getNamedParams(args);
}

鍦?a href="https://www.cnblogs.com/lifullmoon/p/14014934.html">銆婂熀纭€鏀寔灞傘€?/strong>鐨?strong>鍙嶅皠妯″潡鐨?strong>ParamNameResolver灏忚妭宸茬粡鍒嗘瀽杩囪鏂规硶锛屽彲浠ヨ烦杩囧幓鐪嬬湅

rowCountResult鏂规硶

rowCountResult(int rowCount)鏂规硶锛屽皢鍙楀奖鍝嶈鏁拌浆鎹负缁撴灉锛屾柟娉曞涓嬶細

private Object rowCountResult(int rowCount) {
    final Object result;
    if (method.returnsVoid()) {
        result = null;
    } else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
        result = rowCount;
    } else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
        result = (long) rowCount;
    } else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
        result = rowCount > 0;
    } else {
        throw new BindingException("Mapper method 鈥? + command.getName() + "鈥?has an unsupported return type: "
                + method.getReturnType());
    }
    return result;
}

executeWithResultHandler鏂规硶

executeWithResultHandler(SqlSession sqlSession, Object[] args)鏂规硶锛岄€氳繃鍏ュ弬涓畾涔夌殑ResultHandler缁撴灉澶勭悊鍣ㄦ墽琛屾煡璇紝鏂规硶濡備笅锛?/p>

private void executeWithResultHandler(SqlSession sqlSession, Object[] args) {
    // <1> 鑾峰緱 MappedStatement 瀵硅薄
    MappedStatement ms = sqlSession.getConfiguration().getMappedStatement(command.getName());
    /*
     * <2> 閰嶇疆鏍¢獙
     * 鍥犱负鍏ュ弬瀹氫箟浜?ResultHandler 缁撴灉澶勭悊鍣紝鎵€浠ュ鏋滀笉鏄瓨鍌ㄨ繃绋嬶紝涓旀病鏈夐厤缃繑鍥炵粨鏋滅殑 Java Type锛屽垯浼氭姏鍑哄紓甯?     */
    if (!StatementType.CALLABLE.equals(ms.getStatementType())
            && void.class.equals(ms.getResultMaps().get(0).getType())) {
        throw new BindingException(
                "method " + command.getName() + " needs either a @ResultMap annotation, a @ResultType annotation,"
                        + " or a resultType attribute in XML so a ResultHandler can be used as a parameter.");
    }
    // <3> 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
    Object param = method.convertArgsToSqlCommandParam(args);
    // <4> 鎵ц鏁版嵁搴撴煡璇㈡搷浣?    if (method.hasRowBounds()) { // <4.1> 鍏ュ弬瀹氫箟浜?RowBounds 鍒嗛〉瀵硅薄
      // <4.1.1> 鑾峰彇鍏ュ弬瀹氫箟浜?RowBounds 鍒嗛〉瀵硅薄
        RowBounds rowBounds = method.extractRowBounds(args);
        // <4.1.2> 鎵ц鏌ヨ
        sqlSession.select(command.getName(), param, rowBounds, method.extractResultHandler(args));
    } else {
      // <4.2> 鎵ц鏌ヨ
        sqlSession.select(command.getName(), param, method.extractResultHandler(args));
    }
}
  1. 鑾峰緱 MappedStatement 瀵硅薄
  2. 閰嶇疆鏍¢獙锛屽洜涓哄叆鍙傚畾涔変簡 ResultHandler 缁撴灉澶勭悊鍣紝鎵€浠ュ鏋滀笉鏄瓨鍌ㄨ繃绋嬶紝涓旀病鏈夐厤缃繑鍥炵粨鏋滅殑 Java Type锛屽垯浼氭姏鍑哄紓甯?/li>
  3. 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
  4. 鎵ц鏁版嵁搴撴煡璇㈡搷浣?
    1. 鍏ュ弬瀹氫箟浜?RowBounds 鍒嗛〉瀵硅薄锛屽垯鑾峰彇璇ュ璞★紝鐒跺悗鎵ц鏌ヨ锛屼紶鍏ュ垎鏋愬璞?/li>
    2. 娌℃湁瀹氫箟鍒欐墽琛屾墽琛屾煡璇?/li>

executeForMany鏂规硶

executeForMany(SqlSession sqlSession, Object[] args)鏂规硶锛屾墽琛屾煡璇紝杩斿洖鍒楄〃锛屾柟娉曞涓嬶細

private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
    List<E> result;
    // 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
    Object param = method.convertArgsToSqlCommandParam(args);
    // 鎵ц鏁版嵁搴撴煡璇㈡搷浣?    if (method.hasRowBounds()) {
        RowBounds rowBounds = method.extractRowBounds(args);
        // 鎵ц鏌ヨ锛岃繑鍥?List 闆嗗悎
        result = sqlSession.selectList(command.getName(), param, rowBounds);
    } else {
      // 鎵ц鏌ヨ锛岃繑鍥?List 闆嗗悎
        result = sqlSession.selectList(command.getName(), param);
    }
    // issue #510 Collections & arrays support
    // 灏佽 Array 鎴?Collection 缁撴灉
    if (!method.getReturnType().isAssignableFrom(result.getClass())) { // 濡傛灉涓嶆槸 List 闆嗗悎绫诲瀷
        if (method.getReturnType().isArray()) {
          	// 灏?List 杞崲鎴?Array 鏁扮粍绫诲瀷鐨勭粨鏋?            return convertToArray(result);
        } else {
          	// 杞崲鎴愬叾浠?Collection 闆嗗悎绫诲瀷鐨勭粨鏋?            return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
        }
    }
    // 鐩存帴杩斿洖 List 闆嗗悎绫诲瀷鐨勭粨鏋?    return result;
}
  1. 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
  2. 鎵ц鏁版嵁搴撴煡璇㈡搷浣滐紝鑾峰彇鍒?List 闆嗗悎缁撴灉
  3. 鏍规嵁杩斿洖缁撴灉鐨勭被鍨嬭繘琛岃浆鎹?
    1. 濡傛灉鏄?Array 鏁扮粍绫诲瀷锛屽垯灏?List 杞崲鎴?Array 鏁扮粍绫诲瀷鐨勭粨鏋?/li>
    2. 濡傛灉鏄叾浠栭泦鍚堢被鍨嬶紝鍒欏皢 List 杞崲鎴愬叾浠?Collection 闆嗗悎绫诲瀷鐨勭粨鏋?/li>
    3. 鍚﹀垯鐩存帴杩斿洖 List 闆嗗悎绫诲瀷鐨勭粨鏋?/li>

executeForMap鏂规硶

executeForMap(SqlSession sqlSession, Object[] args)鏂规硶锛屾墽琛屾煡璇紝杩斿洖Map锛屾柟娉曞涓嬶細

private <K, V> Map<K, V> executeForMap(SqlSession sqlSession, Object[] args) {
    Map<K, V> result;
    // 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
    Object param = method.convertArgsToSqlCommandParam(args);
    // 鎵ц SELECT 鎿嶄綔
    if (method.hasRowBounds()) {
        RowBounds rowBounds = method.extractRowBounds(args);
  		// 鎵ц鏌ヨ锛岃繑鍥?Map 闆嗗悎
        result = sqlSession.selectMap(command.getName(), param, method.getMapKey(), rowBounds);
    } else {
  		// 鎵ц鏌ヨ锛岃繑鍥?Map 闆嗗悎
        result = sqlSession.selectMap(command.getName(), param, method.getMapKey());
    }
    return result;
}
  1. 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
  2. 鎵ц鏌ヨ锛岃繑鍥?Map 闆嗗悎

鎬荤粨

鏈垎鍒嗘瀽浜?SqlSession 浼氳瘽鍦?MyBatis 涓槸濡備綍琚垱寤猴紝濡備綍鑾峰彇鍒?Mapper 鎺ュ彛鐨勫姩鎬佷唬鐞嗗璞★紝閫氳繃璇ュ姩鎬佷唬鐞嗗璞℃槸濡備綍鎵ц SQL 鐨?/p>

  1. SqlSessionFactoryBuilder鏋勯€犲櫒鎻愪緵build鏂规硶锛屾牴鎹?code>mybatis-config.xml閰嶇疆鏂囦欢瀵?MyBatis 杩涜鍒濆鍖栵紝鐢熸垚Configuration瀵硅薄锛岀敤浜庢瀯寤轰竴涓?code>DefaultSqlSessionFactory瀵硅薄

  2. 閫氳繃1鐢熸垚鐨?SqlSession 宸ュ巶瀵硅薄锛屾垜浠彲浠ユ瀯寤轰竴涓?code>DefaultSqlSession浼氳瘽瀵硅薄锛岄€氳繃杩欎釜浼氳瘽瀵硅薄鐨?code>getMapper(Class<T> mapper)鏂规硶锛屽彲浠ヤ负 Mapper 鎺ュ彛鍒涘缓涓€涓?code>鍔ㄦ€佷唬鐞嗗璞?/code>锛圝DK鍔ㄦ€佷唬鐞嗭級锛屽叾鍔ㄦ€佷唬鐞嗙被涓?code>MapperProxy瀵硅薄

  3. 璋冪敤 Mapper 鎺ュ彛鐨勬煇涓柟娉曟椂锛屼細杩涘叆鐩稿簲鐨?code>MapperProxy浠g悊绫伙紝鏍规嵁鏂规硶瀵瑰簲鐨?code>MapperMethod瀵硅薄锛屾墽琛屾暟鎹簱鎿嶄綔

  4. 鎵ц鏁版嵁搴撶浉鍏虫搷浣滐紝璋冪敤鐨勫氨鏄笂闈㈢殑DefaultSqlSession浼氳瘽瀵硅薄鐨勭浉鍏虫柟娉曪紝璇ヤ細璇濆唴閮ㄥ垯浼氶€氳繃Executor鎵ц鍣ㄥ幓鎵ц鏁版嵁搴撶殑鐩稿叧鎿嶄綔锛屽苟杩斿洖鎵ц缁撴灉

濂戒簡锛屽浜?MyBatis 鏁翠綋涓婃墍鏈夌殑鍐呭宸茬粡鍏ㄩ儴鍒嗘瀽瀹屼簡锛岀浉淇″ぇ瀹跺 MyBatis 鏈変簡涓€涓叏闈㈣璇嗭紝鍏朵腑鑲畾鏈変笉瀵规垨鑰呰糠鎯戠殑鍦版柟锛屾杩庢寚姝o紒锛侊紒鎰熻阿澶у鐨勯槄璇伙紒锛侊紒??????

鍙傝€冩枃绔狅細鑺嬮亾婧愮爜銆婄簿灏?MyBatis 婧愮爜鍒嗘瀽銆?/a>

以上是关于绮惧敖 MyBatis 婧愮爜鍒嗘瀽 - SqlSession 浼氳瘽涓?SQL 鎵ц鍏ュ彛的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList婧愮爜鍒嗘瀽

JDK婧愮爜鍒嗘瀽鍒濇鏁寸悊

Memcached婧愮爜鍒嗘瀽涔媔tems.c

log4j2婧愮爜鍒嗘瀽-1

婧愮爜鍒嗘瀽涔?--HashMap鏌ユ壘銆佸垹闄ゃ€侀亶鍘?/h1>

鏁欏コ鏈嬪弸璇绘噦绯诲垪锛歞ubbo鐨勫彲鎵╁睍鏈哄埗SPI 婧愮爜鍒嗘瀽