绮惧敖 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鏁翠綋鍥撅細
鍦ㄥ崟鐙娇鐢?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();
}
}
- 鑾峰緱
Environment
褰撳墠鐜瀵硅薄 - 閫氳繃
getTransactionFactoryFromEnvironment
鏂规硶锛屼粠 Environment 鐜瀵硅薄涓?code>TransactionFactory瀵硅薄锛岀敤浜庡垱寤轰竴涓?code>Transaction浜嬪姟 - 鐒跺悗鍐嶅垱寤轰竴涓?code>Executor鎵ц鍣ㄥ璞?/li>
- 鏍规嵁鍏ㄥ眬閰嶇疆瀵硅薄銆佹墽琛屽櫒鍜屼簨鍔℃槸鍚﹁嚜鍔ㄦ彁浜ゅ垱寤轰竴涓?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>
鍦?a href="https://www.cnblogs.com/lifullmoon/p/14014934.html">銆婂熀纭€鏀寔灞傘€?/strong>鐨?strong>Binding妯″潡宸茬粡璁茶繃浜嗙浉鍏崇殑鍐呭锛屼緥濡傜湅鍒板墠闈?strong>绀轰緥鐨勭4
姝ワ紝閫氳繃DefaultSqlSession
鐨?code>getMapper鏂规硶浼氭墽琛屼互涓嬫搷浣滐細
- 鍒涘缓Mapper鎺ュ彛瀵瑰簲鐨?code>MapperProxyFactory鍔ㄦ€佷唬鐞嗗璞″伐鍘?/li>
- 閫氳繃杩欎釜宸ュ巶鐨?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>
鏌ヨ璇彞鐨勮瘽灏卞垎涓轰互涓嬪嚑绉嶆儏鍐碉細
- 鏃犺繑鍥烇紝涓斿叆鍙備腑鏈?
ResultHandler
缁撴灉澶勭悊鍣紝鍒欒皟鐢?code>executeWithResultHandler鏂规硶锛屾墽琛屾煡璇紝杩斿洖缁撴灉璁剧疆涓簄ull - 杩斿洖瀵硅薄涓哄鏉℃暟鎹紝鍒欒皟鐢?code>executeForMany鏂规硶锛屾墽琛屾煡璇紝杩斿洖鍒楄〃
- 杩斿洖瀵硅薄涓篗ap绫诲瀷锛屽垯璋冪敤
executeForMap
鏂规硶锛屾墽琛屾煡璇紝杩斿洖Map - 杩斿洖瀵硅薄涓篊ursor绫诲瀷锛屽垯璋冪敤
executeForCursor
鏂规硶锛屾墽琛屾煡璇紝杩斿洖Cursor - 杩斿洖瀵硅薄涓哄崟涓璞★紝鍒欒皟鐢?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));
}
}
- 鑾峰緱
MappedStatement
瀵硅薄 - 閰嶇疆鏍¢獙锛屽洜涓哄叆鍙傚畾涔変簡
ResultHandler
缁撴灉澶勭悊鍣紝鎵€浠ュ鏋滀笉鏄瓨鍌ㄨ繃绋嬶紝涓旀病鏈夐厤缃繑鍥炵粨鏋滅殑 Java Type锛屽垯浼氭姏鍑哄紓甯?/li> - 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
- 鎵ц鏁版嵁搴撴煡璇㈡搷浣?
- 鍏ュ弬瀹氫箟浜?
RowBounds
鍒嗛〉瀵硅薄锛屽垯鑾峰彇璇ュ璞★紝鐒跺悗鎵ц鏌ヨ锛屼紶鍏ュ垎鏋愬璞?/li> - 娌℃湁瀹氫箟鍒欐墽琛屾墽琛屾煡璇?/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;
}
- 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
- 鎵ц鏁版嵁搴撴煡璇㈡搷浣滐紝鑾峰彇鍒?List 闆嗗悎缁撴灉
- 鏍规嵁杩斿洖缁撴灉鐨勭被鍨嬭繘琛岃浆鎹?
- 濡傛灉鏄?Array 鏁扮粍绫诲瀷锛屽垯灏?List 杞崲鎴?Array 鏁扮粍绫诲瀷鐨勭粨鏋?/li>
- 濡傛灉鏄叾浠栭泦鍚堢被鍨嬶紝鍒欏皢 List 杞崲鎴愬叾浠?Collection 闆嗗悎绫诲瀷鐨勭粨鏋?/li>
- 鍚﹀垯鐩存帴杩斿洖 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;
}
- 鑾峰彇鍙傛暟鍚嶇О涓庡叆鍙傜殑鏄犲皠
- 鎵ц鏌ヨ锛岃繑鍥?Map 闆嗗悎
鎬荤粨
鏈垎鍒嗘瀽浜?SqlSession 浼氳瘽鍦?MyBatis 涓槸濡備綍琚垱寤猴紝濡備綍鑾峰彇鍒?Mapper 鎺ュ彛鐨勫姩鎬佷唬鐞嗗璞★紝閫氳繃璇ュ姩鎬佷唬鐞嗗璞℃槸濡備綍鎵ц SQL 鐨?/p>
-
SqlSessionFactoryBuilder
鏋勯€犲櫒鎻愪緵build
鏂规硶锛屾牴鎹?code>mybatis-config.xml閰嶇疆鏂囦欢瀵?MyBatis 杩涜鍒濆鍖栵紝鐢熸垚Configuration
瀵硅薄锛岀敤浜庢瀯寤轰竴涓?code>DefaultSqlSessionFactory瀵硅薄 -
閫氳繃
1
鐢熸垚鐨?SqlSession 宸ュ巶瀵硅薄锛屾垜浠彲浠ユ瀯寤轰竴涓?code>DefaultSqlSession浼氳瘽瀵硅薄锛岄€氳繃杩欎釜浼氳瘽瀵硅薄鐨?code>getMapper(Class<T> mapper)鏂规硶锛屽彲浠ヤ负 Mapper 鎺ュ彛鍒涘缓涓€涓?code>鍔ㄦ€佷唬鐞嗗璞?/code>锛圝DK鍔ㄦ€佷唬鐞嗭級锛屽叾鍔ㄦ€佷唬鐞嗙被涓?code>MapperProxy瀵硅薄 -
璋冪敤 Mapper 鎺ュ彛鐨勬煇涓柟娉曟椂锛屼細杩涘叆鐩稿簲鐨?code>MapperProxy浠g悊绫伙紝鏍规嵁鏂规硶瀵瑰簲鐨?code>MapperMethod瀵硅薄锛屾墽琛屾暟鎹簱鎿嶄綔
-
鎵ц鏁版嵁搴撶浉鍏虫搷浣滐紝璋冪敤鐨勫氨鏄笂闈㈢殑
DefaultSqlSession
浼氳瘽瀵硅薄鐨勭浉鍏虫柟娉曪紝璇ヤ細璇濆唴閮ㄥ垯浼氶€氳繃Executor
鎵ц鍣ㄥ幓鎵ц鏁版嵁搴撶殑鐩稿叧鎿嶄綔锛屽苟杩斿洖鎵ц缁撴灉
濂戒簡锛屽浜?MyBatis 鏁翠綋涓婃墍鏈夌殑鍐呭宸茬粡鍏ㄩ儴鍒嗘瀽瀹屼簡锛岀浉淇″ぇ瀹跺 MyBatis 鏈変簡涓€涓叏闈㈣璇嗭紝鍏朵腑鑲畾鏈変笉瀵规垨鑰呰糠鎯戠殑鍦版柟锛屾杩庢寚姝o紒锛侊紒鎰熻阿澶у鐨勯槄璇伙紒锛侊紒??????
鍙傝€冩枃绔狅細鑺嬮亾婧愮爜銆婄簿灏?MyBatis 婧愮爜鍒嗘瀽銆?/a>
以上是关于绮惧敖 MyBatis 婧愮爜鍒嗘瀽 - SqlSession 浼氳瘽涓?SQL 鎵ц鍏ュ彛的主要内容,如果未能解决你的问题,请参考以下文章