mybatis-spring干了哪些你應(yīng)該知道的勾當(dāng)之SqlSessionFactoryBean?

引子

如果你是一個服務(wù)端開發(fā)者襟诸,而你的主要語言又是Java的話瓦堵,如果還不知道MyBatis和Spring這二大利器,那我只能對你說:出門右轉(zhuǎn)找百度歌亲,左轉(zhuǎn)找谷歌菇用!

  • MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL应结、存儲過程以及高級映射刨疼。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設(shè)置參數(shù)以及獲取結(jié)果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生信息鹅龄,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java對象)映射成數(shù)據(jù)庫中的記錄揩慕。
  • Spring 是一個開放源代碼的設(shè)計層面框架,它解決的是業(yè)務(wù)邏輯層和其他各層的松耦合問題扮休,因此它將面向接口的編程思想貫穿整個系統(tǒng)應(yīng)用迎卤。Spring是于2003 年興起的一個輕量級的Java 開發(fā)框架,由Rod Johnson創(chuàng)建玷坠。簡單來說蜗搔,Spring是一個分層的JavaSE/EE full-stack(一站式)輕量級開源框架劲藐。
  • MyBatis-Spring 幫助你將 MyBatis 代碼無縫地整合到 Spring 中。 使用這個類庫中的類, Spring 將會加載必要的 MyBatis 工廠類和 session 類樟凄。 這個類庫也提供一個簡單的方式來注入 MyBatis 數(shù)據(jù)映射器和 SqlSession 到業(yè)務(wù)層的 bean 中聘芜。 而且它也會處理事務(wù), 翻譯 MyBatis 的異常到 Spring 的 DataAccessException 異常中。最終,它并 不會依賴于 MyBatis,Spring 或 MyBatis-Spring 來構(gòu)建應(yīng)用程序代碼缝龄。

通過上面各組件官網(wǎng)上的解釋我們已經(jīng)知道各個是干什么用的吧汰现!

SqlSessionFactoryBean

在基本的MyBatis中,SqlSessionFactory可以使用SqlSessionFactoryBuilder來創(chuàng)建叔壤,而在mybatis-spring中瞎饲,則使用SqlSessionFactoryBean來創(chuàng)建。
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的類設(shè)計如下圖:


SqlSessionFactoryBean設(shè)計圖

注意: SqlSessionFactoryBean實現(xiàn)了Spring的FactoryBean接口這就說明了由 Spring 最終創(chuàng)建的 bean 不是SqlSessionFactoryBean 本身, 而是工廠類的 getObject()返回的方法的結(jié)果 炼绘,即SqlSessionFactory對象嗅战。
具體的實現(xiàn)源代碼如下:

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的構(gòu)建優(yōu)先級為:
    // 1. configuration屬性,
    // 2. configLocation俺亮,MyBatis的配置文件驮捍,通常在為“WEB-INF/mybatis-configuration.xml”
    // 3. 如果上面二個屬性都沒有設(shè)置,則使用默認(rèn)的配置信息
    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);
      }
    }
    // 省略部分設(shè)置configuration屬性代碼
    // ...

    // 這里脚曾,如果配置的xxxMapper.xml文件的路徑厌漂,會循環(huán)解析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();
        }
      }
     }
    }
   
    // 這里根據(jù)configuration構(gòu)建出SqlSessionFactory
    return this.sqlSessionFactoryBuilder.build(configuration);
  }

  // ...
}

從這個類中我們可以看到,buildSqlSessionFactory干了主要的工作斟珊,從Configuration的初始化苇倡,到Configuration中各個屬性值的設(shè)置,以及Mapper的xml文件解析囤踩。

屬性

  • DataSource - SqlSessionFactory有一個單獨(dú)的必須屬性就是JDBC的DataSource.
  • mapperLocations - 如果MyBatis映射器XML文件在和映射器類相同的路徑下不存在旨椒,那么就需要配置這個屬性;使用這個配置有兩種選擇:
  1. 手動在MyBatis的XML配置文件中使用<mappers>部分來指定類路徑堵漱;
  2. 使用SqlSessionFactoryBean的mapperLocations屬性综慎;

至此,SqlSessionFactoryBean類的功能基本講完了勤庐,如果你有其他想法和意見可以下在方留言~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末示惊,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子愉镰,更是在濱河造成了極大的恐慌米罚,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丈探,死亡現(xiàn)場離奇詭異录择,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進(jìn)店門隘竭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來塘秦,“玉大人,你說我怎么就攤上這事动看∽鹛蓿” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵菱皆,是天一觀的道長赋兵。 經(jīng)常有香客問我,道長搔预,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任叶组,我火速辦了婚禮拯田,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甩十。我一直安慰自己船庇,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布侣监。 她就那樣靜靜地躺著鸭轮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橄霉。 梳的紋絲不亂的頭發(fā)上窃爷,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天,我揣著相機(jī)與錄音姓蜂,去河邊找鬼按厘。 笑死,一個胖子當(dāng)著我的面吹牛钱慢,可吹牛的內(nèi)容都是我干的逮京。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼束莫,長吁一口氣:“原來是場噩夢啊……” “哼懒棉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起览绿,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤策严,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后饿敲,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體享钞,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了栗竖。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暑脆。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狐肢,靈堂內(nèi)的尸體忽然破棺而出添吗,到底是詐尸還是另有隱情,我是刑警寧澤份名,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布碟联,位于F島的核電站,受9級特大地震影響僵腺,放射性物質(zhì)發(fā)生泄漏鲤孵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一辰如、第九天 我趴在偏房一處隱蔽的房頂上張望普监。 院中可真熱鬧,春花似錦琉兜、人聲如沸凯正。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽廊散。三九已至,卻和暖如春梧疲,著一層夾襖步出監(jiān)牢的瞬間允睹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工幌氮, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留擂找,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓浩销,卻偏偏與公主長得像贯涎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子慢洋,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,107評論 2 356