與spring的接合,關鍵是要建立SqlSessionFactory,Spring提供了一個SpringSessionFactoryBean。咱們能夠快速建立SqlSessionFactory。這裏通常只提供XML的路徑。爲何不提供class接口,是由於咱們須要經過Spring管理Bean。因此須要ClassPathMapperScanner類。該類能夠掃描特定的接口,通常是Mapper或者MapperScan。MapperScan更強大,它能夠本身調用因此須要ClassPathMapperScanner類,緣由是上面有個@Import(MapperScannerRegistrar.class)註解。
Spring經過代理接口獲得Bean對象。產生代理類須要用到SqlSessionFactory。java
@Override public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); }
這裏的getSqlSession實際上獲取到的是一個代理的SeqSession。其實是SeqSessionTemplate。爲何這裏要代理,而不直接使用DefaultSqlSession了。spring
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[] { SqlSession.class }, new SqlSessionInterceptor()); }
答案是事物。若是Spring要管理事物要怎麼作了。 1 spring爲了可以幫你自動提交。必需得能獲取到鏈接,而後執行回滾或提交。因此你的鏈接必須交由spring管理。請看SpringManagedTransaction類。看下面,關鍵是第一行。sql
private void openConnection() throws SQLException { this.connection = DataSourceUtils.getConnection(this.dataSource); this.autoCommit = this.connection.getAutoCommit(); this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource); if (LOGGER.isDebugEnabled()) { LOGGER.debug( "JDBC Connection [" + this.connection + "] will" + (this.isConnectionTransactional ? " " : " not ") + "be managed by Spring"); } }
2 若是你不但願spring管理事物。那麼就是每執完一個insert,update,delete語句,都須要自動提交。這個時候SqlSessionTemplate就起做用了。springboot
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { SqlSession sqlSession = getSqlSession( SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { Object result = method.invoke(sqlSession, args); if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) { // force commit even on non-dirty sessions because some databases require // a commit/rollback before calling close() sqlSession.commit(true); } return result; } catch (Throwable t) { Throwable unwrapped = unwrapThrowable(t); if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) { // release the connection to avoid a deadlock if the translator is no loaded. See issue #22 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); sqlSession = null; Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped); if (translated != null) { unwrapped = translated; } } throw unwrapped; } finally { if (sqlSession != null) { closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } }
OK,與spring的接合結束了。session
這個更簡單。就一個MybatisAutoConfiguration類,該爲會自動建立SqlSessionFactory,SqlSessionTemplate。 同時還會建立AutoConfiguredMapperScannerRegistrar。在該類裏面會掃描mapper註解的class。mybatis
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { logger.debug("Searching for mappers annotated with @Mapper"); ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry); try { if (this.resourceLoader != null) { scanner.setResourceLoader(this.resourceLoader); } List<String> packages = AutoConfigurationPackages.get(this.beanFactory); if (logger.isDebugEnabled()) { for (String pkg : packages) { logger.debug("Using auto-configuration base package '{}'", pkg); } } scanner.setAnnotationClass(Mapper.class); scanner.registerFilters(); scanner.doScan(StringUtils.toStringArray(packages)); } catch (IllegalStateException ex) { logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex); } }
若是不想用mapper,那麼須要MapperScan。隨便放在哪個BEAN上就能夠了。 這裏掃描時,須要注意有這麼一句話。app
if (!explicitFactoryUsed) { if (logger.isDebugEnabled()) { logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'."); } definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); }
最後一句但是很重要的。ide