天天看點

Mybatis整合Spring

Mybatis整合Spring

       根據官方的說法,在ibatis3,也就是Mybatis3問世之前,Spring3的開發工作就已經完成了,是以Spring3中還是沒有對Mybatis3的支援。是以由Mybatis社群自己開發了一個Mybatis-Spring用來滿足Mybatis使用者整合Spring的需求。下面就将通過Mybatis-Spring來整合Mybatis跟Spring的用法做一個簡單的介紹。

       首先,我們需要從Mybatis官網上下載下傳Mybatis-Spring的jar包添加到我們項目的類路徑下,當然也需要添加Mybatis的相關jar包和Spring的相關jar包。我們知道在Mybatis的所有操作都是基于一個SqlSession的,而SqlSession是由SqlSessionFactory來産生的,SqlSessionFactory又是由SqlSessionFactoryBuilder來生成的。但是Mybatis-Spring是基于SqlSessionFactoryBean的。在使用Mybatis-Spring的時候,我們也需要SqlSession,而且這個SqlSession是内嵌在程式中的,一般不需要我們直接通路。SqlSession也是由SqlSessionFactory來産生的,但是Mybatis-Spring給我們封裝了一個SqlSessionFactoryBean,在這個bean裡面還是通過SqlSessionFactoryBuilder來建立對應的SqlSessionFactory,進而擷取到對應的SqlSession。通過SqlSessionFactoryBean我們可以通過對其指定一些屬性來提供Mybatis的一些配置資訊。是以接下來我們需要在Spring的applicationContext配置檔案中定義一個SqlSessionFactoryBean。

       在定義SqlSessionFactoryBean的時候,dataSource屬性是必須指定的,它表示用于連接配接資料庫的資料源。當然,我們也可以指定一些其他的屬性,下面簡單列舉幾個:

 mapperLocations:它表示我們的Mapper檔案存放的位置,當我們的Mapper檔案跟對應的Mapper接口處于同一位置的時候可以不用指定該屬性的值。

configLocation:用于指定Mybatis的配置檔案位置。如果指定了該屬性,那麼會以該配置檔案的内容作為配置資訊建構對應的SqlSessionFactoryBuilder,但是後續屬性指定的内容會覆寫該配置檔案裡面指定的對應内容。

 typeAliasesPackage:它一般對應我們的實體類所在的包,這個時候會自動取對應包中不包括包名的簡單類名作為包括包名的别名。多個package之間可以用逗号或者分号等來進行分隔。

 typeAliases:數組類型,用來指定别名的。指定了這個屬性後,Mybatis會把這個類型的短名稱作為這個類型的别名,前提是該類上沒有标注@Alias注解,否則将使用該注解對應的值作為此種類型的别名。

 plugins:數組類型,用來指定Mybatis的Interceptor。

 typeHandlersPackage:用來指定TypeHandler所在的包,如果指定了該屬性,SqlSessionFactoryBean會自動把該包下面的類注冊為對應的TypeHandler。多個package之間可以用逗号或者分号等來進行分隔。

 typeHandlers:數組類型,表示TypeHandler。

        接下來就是在Spring的applicationContext檔案中定義我們想要的Mapper對象對應的MapperFactoryBean了。通過MapperFactoryBean可以擷取到我們想要的Mapper對象。MapperFactoryBean實作了Spring的FactoryBean接口,是以MapperFactoryBean是通過FactoryBean接口中定義的getObject方法來擷取對應的Mapper對象的。在定義一個MapperFactoryBean的時候有兩個屬性需要我們注入,一個是Mybatis-Spring用來生成實作了SqlSession接口的SqlSessionTemplate對象的sqlSessionFactory;另一個就是我們所要傳回的對應的Mapper接口了。

       定義好相應Mapper接口對應的MapperFactoryBean之後,我們就可以把我們對應的Mapper接口注入到由Spring管理的bean對象中了,比如Service bean對象。這樣當我們需要使用到相應的Mapper接口時,MapperFactoryBean會從它的getObject方法中擷取對應的Mapper接口,而getObject内部還是通過我們注入的屬性調用SqlSession接口的getMapper(Mapper接口)方法來傳回對應的Mapper接口的。這樣就通過把SqlSessionFactory和相應的Mapper接口交給Spring管理實作了Mybatis跟Spring的整合。

Spring的applicationContext.xml配置檔案:

BlogMapper.xml檔案:

BlogMapper.java:

BlogServiceImpl.java:

       利用上面的方法進行整合的時候,我們有一個Mapper就需要定義一個對應的MapperFactoryBean,當我們的Mapper比較少的時候,這樣做也還可以,但是當我們的Mapper相當多時我們再這樣定義一個個Mapper對應的MapperFactoryBean就顯得速度比較慢了。為此Mybatis-Spring為我們提供了一個叫做MapperScannerConfigurer的類,通過這個類Mybatis-Spring會自動為我們注冊Mapper對應的MapperFactoryBean對象。

       如果我們需要使用MapperScannerConfigurer來幫我們自動掃描和注冊Mapper接口的話我們需要在Spring的applicationContext配置檔案中定義一個MapperScannerConfigurer對應的bean。對于MapperScannerConfigurer而言有一個屬性是我們必須指定的,那就是basePackage。basePackage是用來指定Mapper接口檔案所在的基包的,在這個基包或其所有子包下面的Mapper接口都将被搜尋到。多個基包之間可以使用逗号或者分号進行分隔。最簡單的MapperScannerConfigurer定義就是隻指定一個basePackage屬性,如:

       這樣MapperScannerConfigurer就會掃描指定基包下面的所有接口,并把它們注冊為一個個MapperFactoryBean對象。當使用MapperScannerConfigurer加basePackage屬性的時候,我們上面例子的applicationContext配置檔案将變為這樣:

有時候我們指定的基包下面的并不全是我們定義的Mapper接口,為此MapperScannerConfigurer還為我們提供了另外兩個可以縮小搜尋和注冊範圍的屬性。一個是annotationClass,另一個是markerInterface。

annotationClass:當指定了annotationClass的時候,MapperScannerConfigurer将隻注冊使用了annotationClass注解标記的接口。

markerInterface:markerInterface是用于指定一個接口的,當指定了markerInterface之後,MapperScannerConfigurer将隻注冊繼承自markerInterface的接口。

       如果上述兩個屬性都指定了的話,那麼MapperScannerConfigurer将取它們的并集,而不是交集。即使用了annotationClass進行标記或者繼承自markerInterface的接口都将被注冊為一個MapperFactoryBean。

現在假設我們的Mapper接口都繼承了一個SuperMapper接口,那麼我們就可以這樣來定義我們的MapperScannerConfigurer。

       如果是都使用了注解MybatisMapper标記的話,那麼我們就可以這樣來定義我們的MapperScannerConfigurer。

       除了用于縮小注冊Mapper接口範圍的屬性之外,我們還可以指定一些其他屬性,如:

 sqlSessionFactory:這個屬性已經廢棄。當我們使用了多個資料源的時候我們就需要通過sqlSessionFactory來指定在注冊MapperFactoryBean的時候需要使用的SqlSessionFactory,因為在沒有指定sqlSessionFactory的時候,會以Autowired的方式自動注入一個。換言之當我們隻使用一個資料源的時候,即隻定義了一個SqlSessionFactory的時候我們就可以不給MapperScannerConfigurer指定SqlSessionFactory。

sqlSessionFactoryBeanName:它的功能跟sqlSessionFactory是一樣的,隻是它指定的是定義好的SqlSessionFactory對應的bean名稱。

sqlSessionTemplate:這個屬性已經廢棄。它的功能也是相當于sqlSessionFactory的,因為就像前面說的那樣,MapperFactoryBean最終還是使用的SqlSession的getMapper方法取的對應的Mapper對象。當定義有多個SqlSessionTemplate的時候才需要指定它。對于一個MapperFactoryBean來說SqlSessionFactory和SqlSessionTemplate隻需要其中一個就可以了,當兩者都指定了的時候,SqlSessionFactory會被忽略。

sqlSessionTemplateBeanName:指定需要使用的sqlSessionTemplate對應的bean名稱。

注意:由于使用sqlSessionFactory和sqlSessionTemplate屬性時會使一些内容在PropertyPlaceholderConfigurer之前加載,導緻在配置檔案中使用到的外部屬性資訊無法被及時替換而出錯,是以官方現在新的Mybatis-Spring中已經把sqlSessionFactory和sqlSessionTemplate屬性廢棄了,推薦大家使用sqlSessionFactoryBeanName屬性和sqlSessionTemplateBeanName屬性。

       除了上述整合之後直接使用Mapper接口之外,Mybatis-Spring還為我們提供了一種直接使用SqlSession的方式。Mybatis-Spring為我們提供了一個實作了SqlSession接口的SqlSessionTemplate類,它是線程安全的,可以被多個Dao同時使用。同時它還跟Spring的事務進行了關聯,確定目前被使用的SqlSession是一個已經和Spring的事務進行綁定了的。而且它還可以自己管理Session的送出和關閉。當使用了Spring的事務管理機制後,SqlSession還可以跟着Spring的事務一起送出和復原。

       使用SqlSessionTemplate時我們可以在Spring的applicationContext配置檔案中如下定義:

    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">

       <constructor-arg index="0" ref="sqlSessionFactory" />

    </bean>

       這樣我們就可以通過Spring的依賴注入在Dao中直接使用SqlSessionTemplate來程式設計了,這個時候我們的Dao可能是這個樣子:

 注:

      本文是基于Mybatis3.2.1、Mybatis-Spring1.1.0和Spring3.1寫的。