javascript
Spring-Spring整合MyBatis详解
文章目錄
- 概述
- 項目結構
- 配置SQLMapClient
- 在Spring中配置MyBatis
- 編寫Mybatis的DAO
- 使用SqlSessionTemplate
- 使用映射接口
- Code
概述
使用Mybatis提供的ORM機制,面對具體的數據操作,Mybatis要求開發者編程具體的SQL語句。 相對于Hibernate等全自動的ORM機制而言,Mybatis在開發的工作量和數據庫移植性上做出了讓步,為數據持久化操作提供了更大的自由空間。
Mybatis的事務管理可以由Spring標準機制進行處理,它和Spring JDBC事務管理的方式完全一致,采用和SpringJDBC相同的DataSourceTransactionManager事務管理器。
項目結構
配置SQLMapClient
每個Mybatis的應用程序都以一個SqlSessionFactory對象的實例為核心。
SqlSessionFactory對象的實例可以通過SqlSessionFactoryBuilder對象來獲得。 SqlSessionFactoryBuilder對象可以從XML配置文件或者Configuration類的實例中構建SqlSessionFactory對象。
和Hibernate相似,Mybatis擁有多個SQL映射文件,并通過一個配置文件對這些SQL映射文件進行裝配,同時在該文件中定義一些控制屬性的信息。
我們來看一個簡單的Mybatis配置文件
myBatisConfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><settings><!-- (1) 提供可控制Mybatis框架運行行為的屬性信息 --><setting name="lazyLoadingEnabled" value="false" /></settings><typeAliases><!-- (2) 定義全限定類名的別名,在映射文件中可以通過別名代替具體的類名 --><typeAlias alias="Artisan" type="com.artisan.domain.Artisan" /></typeAliases> </configuration>在(1)處提供提供可控制Mybatis框架運行行為的屬性信息 ,在(2)處定義全限定類名的別名,在映射文件中可以通過別名代替具體的類名,簡化配置。
當然我們也可以定義mappers標簽引用SQL映射文件,如果我們在MyBatis的總裝配置文件myBatisConfig.xml中指定SQL映射文件,則必須逐個列出所有的SQL映射文件,比較繁瑣。我們更傾向于 通過SqlSessionFactoryBean提供的mapperLocations屬性文件,通過掃描式加載SQL映射文件。 (下文描述)
我們來看下SQL映射文件的內容:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- (1)指定命名空間 --> <mapper namespace="com.artisan.dao.mybatis.ArtisanMybatisDao"><insert id="addArtisan" parameterType="Artisan">INSERT INTO littel_artisan(artisan_id,artisan_name,artisan_desc)VALUES(#{artisanId},#{artisanName}, #{artisanDesc})</insert><select id="selectArtisan" resultType="Artisan" parameterType="String">select artisan_id artisanId,artisan_name artisanName,artisan_desc artisanDescfrom little_artisanwhere artisan_name = #{artisanName}</select> </mapper>該配置文件定義了Artisan實體類機型數據操作時所需要的SQL,同事還定義了查詢結果和對象屬性的映射關系。(這里我們僅僅列出一個查詢示例)。
在(1)指定命名空間,每個具體的映射項都有一個id,可以通過命名空間和映射項的id定位到具體的映射項。
-
映射項的parameterType指定傳入的參數對象,可以是全限定名的二類,也可以是類的別名(別名在Mybatis的主配置文件中定義)比如 <typeAlias alias="Artisan" type="com.artisan.domain.Artisan" />
-
如果映射項的入參是基礎類型或者String類型,則可以通過使用int 、long、String的基礎類型名。
-
如果映射項擁有返回類型對象,通過resultType指定。
-
在映射項中通過#{XXX}綁定parameterType指定參數類的屬性,支持級聯屬性,比如{anotherDomain.anotherProperty}
在Spring中配置MyBatis
我們使用Mybatis提供的mybatis-spring整合類包實現Spring和Mybatis的整合。 我們添加將mybatis-spring構建pom.xml。
<!-- mybatis ORM框架 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><!-- mybatis-spring適配器 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>${mybatis-spring.version}</version></dependency>我們來看下Spring配置Mybatis的配置文件 applicationContext-mybatis.xml
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd"><!-- 掃描類包,將標注Spring注解的類自動轉化Bean,同時完成Bean的注入 --><context:component-scan base-package="com.artisan" resource-pattern="**/mybatis/*.class"/><!-- spring里使用org.mybatis.spring.mapper.MapperScannerConfigurer 進行自動掃描的時候,設置了sqlSessionFactory 的話,可能會導致PropertyPlaceholderConfigurer失效,也就是用${jdbc.username}這樣之類的表達式,將無法獲取到properties文件里的內容。 導致這一原因是因為,MapperScannerConigurer實際是在解析加載bean定義階段的,這個時候要是設置sqlSessionFactory的話,會導致提前初始化一些類,這個時候PropertyPlaceholderConfigurer還沒來得及替換定義中的變量,導致把表達式當作字符串復制了。但如果不設置sqlSessionFactory 屬性的話,就必須要保證sessionFactory在spring中名稱一定要是sqlSessionFactory,否則就無法自動注入。解決思路: 主要改動了MapperScannerConfigurer的配置,使用sqlSessionFactoryBeanName進行延遲注入 --><!-- 如果Spring和Mybatis整合,要想使用context:property-placeholder.MapperScannerConfigurer中 p:sqlSessionFactoryBeanName="sqlSessionFactory" 這樣配置--><context:property-placeholder location="classpath:spring/jdbc.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close" p:driverClassName="${jdbc.driverClassName}"p:url="${jdbc.url}" p:username="${jdbc.username}" p:password="${jdbc.password}" /><!-- 通過Spring風格構建Mybatis的SqlSessionFactory --><bean id="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"p:dataSource-ref="dataSource"p:configLocation="classpath:mybatis/myBatisConfig.xml"p:mapperLocations="classpath:com/artisan/domain/mybatis/*.xml"/><!-- 創建Mybatis訪問數據庫的模板類 --><bean class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg ref="sqlSessionFactory"/></bean><!-- 查 找 類 路 徑 下 的 映 射 器 并 自 動 將 它 們 創 建 成 MapperFactoryBean --><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"p:sqlSessionFactoryBeanName="sqlSessionFactory"p:basePackage="com.artisan.dao.mybatis"/><!-- 暫未用到事務 --><!-- Spring的事務管理器 <bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"p:dataSource-ref="dataSource"/>--><!-- 開啟事務注解 <tx:annotation-driven transaction-manager="transactionManager"/>--> </beans>mybatis-spring類包提供了一個SqlSessionFactoryBean,以便通過Spring風格創建Mybatis的SqlSessionFactory。只需要注入數據源并指定Mybatis的總裝配置文件那就可以啦。
我們通過 p:mapperLocations="classpath:com/artisan/domain/mybatis/*.xml ,SqlSessionFactoryBean將掃描com/artisan/domain/mybatis類路徑并加載所有以.xml為后綴的映射文件。
編寫Mybatis的DAO
使用SqlSessionTemplate
mybatis-spring效仿Spring的風格提供了一個模板類SQLSessionTemplate,可以通過模板輕松的訪問數據庫。
首先在applicationContext-mybatis.xml中配置SQLSessionTemplate
<!-- 創建Mybatis訪問數據庫的模板類 --><bean class="org.mybatis.spring.SqlSessionTemplate"><constructor-arg ref="sqlSessionFactory"/></bean>然后就可以通過SqlSessionTemplate調用SQL映射項完成數據訪問操作
使用映射接口
Mybatis提供了一種可將SQL映射文件中的映射項通過名稱匹配接口進行調用的方法: 接口名稱和映射名空間相同,接口方法和映射元素的id相同。
我們在Artisan.xml的映射項中定義一個調用接口
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- (1)指定命名空間 --> <mapper namespace="com.artisan.dao.mybatis.ArtisanMybatisDao"><select id="selectArtisan" resultType="Artisan" parameterType="String">select artisan_id artisanId,artisan_name artisanName,artisan_desc artisanDescfrom little_artisanwhere artisan_name = #{artisanName}</select> </mapper>定義同名接口
package com.artisan.dao.mybatis;import com.artisan.domain.Artisan;public interface ArtisanMybatisDao {Artisan selectArtisan(String artisanName); }接口名為com.artisan.dao.mybatis.ArtisanMybatisDao,Artisan.xml文件中的每個映射項對應一個接口方法,接口方法的嗯簽名和映射項的聲明匹配。
查詢數據
package com.artisan.dao.mybatis;import org.mybatis.spring.SqlSessionTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository;import com.artisan.domain.Artisan;/*** * * @ClassName: ArtisanMybatisDaoImpl* * @Description: @Repository標注的DAO層,被Spring管理* * @author: Mr.Yang* * @date: 2017年10月1日 下午12:18:25*/@Repository public class ArtisanMybatisDaoImpl implements ArtisanMybatisDao {private SqlSessionTemplate sqlSessionTemplate;// 注入SqlSessionTemplate@Autowiredpublic void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {this.sqlSessionTemplate = sqlSessionTemplate;}@Overridepublic Artisan selectArtisan(String artisanName) {// 必須是獲取接口ArtisanMybatisDao artisanMybatisDao = sqlSessionTemplate.getMapper(ArtisanMybatisDao.class);return artisanMybatisDao.selectArtisan(artisanName);}}單元測試
package com.artisan.dao.mybatis;import org.junit.After; import org.junit.Before; import org.junit.Test; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.artisan.domain.Artisan;public class ArtisanMybatisDaoImplTest {ClassPathXmlApplicationContext ctx = null;ArtisanMybatisDaoImpl artisanMybatisDaoImpl = null;@Beforepublic void initContext() {ctx = new ClassPathXmlApplicationContext("spring/applicationContext-mybatis.xml");artisanMybatisDaoImpl = ctx.getBean("artisanMybatisDaoImpl",ArtisanMybatisDaoImpl.class);}@Testpublic void testSelectArtisanWithMybatis() {Artisan artisan = artisanMybatisDaoImpl.selectArtisan("artisan");System.out.println("Artisan Id:" + artisan.getArtisanId());System.out.println("Artisan Name:" + artisan.getArtisanName());System.out.println("Artisan Desc:" + artisan.getArtisanDesc());}@Afterpublic void releaseContext() {if (ctx != null) {ctx.close();}} }輸出結果
十月 01, 2017 1:03:30 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@604b7b51: startup date [Sun Oct 01 13:03:30 BOT 2017]; root of context hierarchy 十月 01, 2017 1:03:31 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring/applicationContext-mybatis.xml] DEBUG LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. DEBUG SqlSessionFactoryBean - Parsed configuration file: 'class path resource [mybatis/myBatisConfig.xml]' DEBUG SqlSessionFactoryBean - Parsed mapper file: 'file [D:\workspace\workspace-sts\SpringMyBaitsDemo\target\classes\com\artisan\domain\mybatis\Artisan.xml]' DEBUG SqlSessionUtils - Creating a new SqlSession DEBUG SqlSessionUtils - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@558cdd] was not registered for synchronization because synchronization is not active DEBUG SpringManagedTransaction - JDBC Connection [jdbc:oracle:thin:@172.25.246.11:1521:testbed, UserName=CC, Oracle JDBC driver] will not be managed by Spring DEBUG selectArtisan - ==> Preparing: select artisan_id artisanId, artisan_name artisanName, artisan_desc artisanDesc from little_artisan where artisan_name = ? DEBUG selectArtisan - ==> Parameters: artisan(String) DEBUG selectArtisan - <== Total: 1 DEBUG SqlSessionUtils - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@558cdd] Artisan Id:AAAYbEAAZAAAK9fAAA Artisan Name:artisan Artisan Desc:Spring+MyBatis Demo 十月 01, 2017 1:03:36 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@604b7b51: startup date [Sun Oct 01 13:03:30 BOT 2017]; root of context hierarchy可以看到從數據庫中獲取的數據如下:
Artisan Id:AAAYbEAAZAAAK9fAAA
Artisan Name:artisan
Artisan Desc:Spring+MyBatis Demo
至此就完成了Spring+Mybatis的整合
Code
源碼已托管到Github:https://github.com/yangshangwei/SpringMyBaitsDemo
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Spring-Spring整合MyBatis详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring4.X系列之Spring J
- 下一篇: Spring Cache-缓存概述及使用