mybatis與spring

mybatis與spring

與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

mybatis與springboot結合。

這個更簡單。就一個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

相關文章
相關標籤/搜索