美文网首页
mybatis-spring干了哪些你应该知道的勾当之SqlSe

mybatis-spring干了哪些你应该知道的勾当之SqlSe

作者: oneape15 | 来源:发表于2019-01-02 23:05 被阅读45次

引子

如果你是一个服务端开发者,而你的主要语言又是Java的话,如果还不知道MyBatis和Spring这二大利器,那我只能对你说:出门右转找百度,左转找谷歌!

  • MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
  • Spring 是一个开放源代码的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式)轻量级开源框架。
  • MyBatis-Spring 帮助你将 MyBatis 代码无缝地整合到 Spring 中。 使用这个类库中的类, Spring 将会加载必要的 MyBatis 工厂类和 session 类。 这个类库也提供一个简单的方式来注入 MyBatis 数据映射器和 SqlSession 到业务层的 bean 中。 而且它也会处理事务, 翻译 MyBatis 的异常到 Spring 的 DataAccessException 异常中。最终,它并 不会依赖于 MyBatis,Spring 或 MyBatis-Spring 来构建应用程序代码。

通过上面各组件官网上的解释我们已经知道各个是干什么用的吧!

SqlSessionFactoryBean

在基本的MyBatis中,SqlSessionFactory可以使用SqlSessionFactoryBuilder来创建,而在mybatis-spring中,则使用SqlSessionFactoryBean来创建。
XML配置方式:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mapperLocations" value="classpath*:mappers/**/*.xml" />
</bean>

Java代写方式:

SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setMapperLocations(resolver.getResources("classpath*:mappers/**/*.xml"));
SqlSessionFactory sessionFactory = factoryBean.getObject();

SqlSessionFactoryBean的类设计如下图:


SqlSessionFactoryBean设计图

注意: SqlSessionFactoryBean实现了Spring的FactoryBean接口这就说明了由 Spring 最终创建的 bean 不是SqlSessionFactoryBean 本身, 而是工厂类的 getObject()返回的方法的结果 ,即SqlSessionFactory对象。
具体的实现源代码如下:

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
  private Resource configLocation;
  private Configuration configuration;
  private Resource[] mapperLocations;
  private DataSource dataSource;
  private TransactionFactory transactionFactory;
  private Properties configurationProperties;
  private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
  private SqlSessionFactory sqlSessionFactory;
  //EnvironmentAware requires spring 3.1
  private String environment = SqlSessionFactoryBean.class.getSimpleName();
  private boolean failFast;
  private Interceptor[] plugins;
  private TypeHandler<?>[] typeHandlers;
  private String typeHandlersPackage;
  private Class<?>[] typeAliases;
  private String typeAliasesPackage;
  private Class<?> typeAliasesSuperType;
  //issue #19. No default provider.
  private DatabaseIdProvider databaseIdProvider;
  private Class<? extends VFS> vfs;
  private Cache cache;
  private ObjectFactory objectFactory;
  private ObjectWrapperFactory objectWrapperFactory;

  // 省略getter和setter
  // ...
  @Override
  public void afterPropertiesSet() throws Exception {
    // 省略属性的断言判断
    // ...
    this.sqlSessionFactory = buildSqlSessionFactory();
  }
  @Override
  public SqlSessionFactory getObject() throws Exception {
    if (this.sqlSessionFactory == null) {
      afterPropertiesSet();
    }
    return this.sqlSessionFactory;
  }

  protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
     Configuration configuration;
    // Configuration的构建优先级为:
    // 1. configuration属性,
    // 2. configLocation,MyBatis的配置文件,通常在为“WEB-INF/mybatis-configuration.xml”
    // 3. 如果上面二个属性都没有设置,则使用默认的配置信息
    XMLConfigBuilder xmlConfigBuilder = null;
    if (this.configuration != null) {
      configuration = this.configuration;
      if (configuration.getVariables() == null) {
        configuration.setVariables(this.configurationProperties);
      } else if (this.configurationProperties != null) {
        configuration.getVariables().putAll(this.configurationProperties);
      }
    } else if (this.configLocation != null) {
      xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
      configuration = xmlConfigBuilder.getConfiguration();
    } else {
      LOGGER.debug(() -> "Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
      configuration = new Configuration();
      if (this.configurationProperties != null) {
        configuration.setVariables(this.configurationProperties);
      }
    }
    // 省略部分设置configuration属性代码
    // ...

    // 这里,如果配置的xxxMapper.xml文件的路径,会循环解析xml文件
    if (!isEmpty(this.mapperLocations)) {
      for (Resource mapperLocation : this.mapperLocations) {
        if (mapperLocation == null) {
          continue;
        }

        try {
          XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
              configuration, mapperLocation.toString(), configuration.getSqlFragments());
          xmlMapperBuilder.parse();
        } catch (Exception e) {
          throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
        } finally {
          ErrorContext.instance().reset();
        }
      }
     }
    }
   
    // 这里根据configuration构建出SqlSessionFactory
    return this.sqlSessionFactoryBuilder.build(configuration);
  }

  // ...
}

从这个类中我们可以看到,buildSqlSessionFactory干了主要的工作,从Configuration的初始化,到Configuration中各个属性值的设置,以及Mapper的xml文件解析。

属性

  • DataSource - SqlSessionFactory有一个单独的必须属性就是JDBC的DataSource.
  • mapperLocations - 如果MyBatis映射器XML文件在和映射器类相同的路径下不存在,那么就需要配置这个属性;使用这个配置有两种选择:
  1. 手动在MyBatis的XML配置文件中使用<mappers>部分来指定类路径;
  2. 使用SqlSessionFactoryBean的mapperLocations属性;

至此,SqlSessionFactoryBean类的功能基本讲完了,如果你有其他想法和意见可以下在方留言~~

相关文章

网友评论

      本文标题:mybatis-spring干了哪些你应该知道的勾当之SqlSe

      本文链接:https://www.haomeiwen.com/subject/kmstrqtx.html