經過前一篇的學習,咱們知道可使用JDBC操做數據庫,但在實際生產中,咱們通常使用MyBatis。在本篇,能夠學習到SpringBoot如何整合MyBatis框架,以及相關自動配置原理。java
MyBatis是目前Java持久層最爲主流的技術之一,它能夠避免幾乎全部的JDBC代碼和手動設置參數以及獲取結果集。同時,MyBatis是基於一種SQL到POJO的模型,須要咱們提供SQL、映射關係以及POJO。因爲本筆記爲SpringBoot系列筆記,故重點放在SpringBoot整合使用MyBatis。spring
注:在說明註解時,第一點加粗爲註解中文含義,第二點爲通常加在哪身上,縮進或代碼塊爲示例,如:sql
@註解數據庫
語句示例
//代碼示例
在SpringBoot中有兩種導入場景方式,一種是初始化導向,另外一種是手動導入。springboot
*這裏須要與前文的兩種配置方式作區別:筆者的導入指往應用中添加相應場景,注重一個從0到1的過程;而前文Druid鏈接池的兩種配置方式雖然也有導入的意思,但更加註重導入後的配置過程,是一個從1到2的過程。mybatis
初始化導向指在新建SpringBoot項目工程時進行導入:
app
手動導入只須要在SpringBoot的pom.xml文件裏添加下面場景便可:框架
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.4</version> </dependency>
MyBatis的自動配置原理跟Druid差很少,咱們能夠經過源碼分析得出能夠本身配置哪些屬性,以及配置這些屬性時的前綴。ide
加入MyBatis場景後,咱們能夠發現該場景裏有:
spring-boot
經過前面的文章,咱們知道SpringBoot會先找到對應場景的自動配置類,在這裏是MybatisAutoConfiguration
@Configuration @ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class }) @ConditionalOnBean(DataSource.class) @EnableConfigurationProperties(MybatisProperties.class) // MyBatis配置項綁定類 @AutoConfigureAfter({ DataSourceAutoConfiguration.class, MybatisLanguageDriverAutoConfiguration.class }) public class MybatisAutoConfiguration { }
從源碼中,咱們能夠獲得如下信息:
跟MybatisProperties
配置類綁定,
配置屬性的前綴爲 mybatis
@ConfigurationProperties(prefix = "mybatis") public class MybatisProperties
全局配置文件:使用Mybatis須要進行全局配置;
SqlSessionFactory: 用來生成SqlSession
;
SqlSessionFactory
);SqlSession:自動配置了SqlSessionTemplate
,能夠生成SqlSession
;
@Import(AutoConfiguredMapperScannerRegistrar.class):導入的類裏有定義如何操做@Mapper
註解的接口;
@Mapper
就會被自動掃描進容器。全局配置文件的書寫方式有三種,分別是配置模式、註解模式以及混合模式。在配置以前,咱們須要作些準備工做,讓SpringBoot知道咱們的配置文件寫在哪裏。
準備工做:
配置全局配置文件位置( 在application.yaml
中指定Mapper配置文件的位置,以及指定全局配置文件的信息,建議配置在mybatis.configuration
);
mybatis: #全局配置文件位置 config-location: classpath:mybatis/mybatis-config.xml #sql映射文件位置 mapper-locations: classpath:mybatis/mapper/*.xml #定義別名掃描的包,須要與@Alias聯合使用 type-aliases-package: …… #具體類須要與@MappedJdbcTypes聯合使用 type-handlers-package: …… #執行器(Executor),能夠配置STMPLE、REUSE、BATCH、默認爲STMPLE executor-type: …… configuration: #配置MyBatis插件(攔截器等) interceptors: …… #級聯延遲加載配置屬性 aggressive-lazy-loading: ……
config-location
與mapper-locations
不能同在,理由以下:config-location
,config-location
的做用是肯定mybatis-config.xml文件位置;而mapper-locations
是用來註冊xxxmapper.xml文件。若是使用了mybatis-config.xml,而且裏面配置了mapper,那就不須要mapper-locations
。編寫mapper接口,使用標準@Mapper
註解( 也能夠在啓動類上加上@MapperScan
替換@Mapper )
映射配置;
用在接口類上
在接口類上添加了@Mapper,在編譯以後會生成相應的接口實現類;
若是有多組接口須要編譯成實現類,須要在每一個接口上標註一個@Mapper;
@Mapper public interface UserDAO { //代碼 }
映射掃描配置;
用在主啓動類下;
指定要變成實現類的接口所在的包,而後包下面的全部接口在編譯以後都會生成相應的實現類;
將MyBatis所需的對應接口掃描到Spring IOC容器中;
能夠解決@Mapper標註過多問題,直接在主啓動類上加上一個@MapperScan便可;
@SpringBootApplication //@MapperScan("com.dlhjw.mapper") @MapperScan( //指定掃描包 basePackages = "com.dlhjw.mapper", //指定SqlSessionFactory,若是sqlSessionTemplate被指定,則做廢 sqlSessionFactoryRef = "sqlSessionFactory", //指定sqlSessionTemplate,將忽略sqlSessionFactory的配置(優先級高) sqlSessionTemplateRef = 「sqlSessionTemplate」, //限制掃描接口,不經常使用 //markerInterface = class.class, annotationClass = Repository.class ) public class SpringbootMybatisDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMybatisDemoApplication.class, args); } }
【如下不經常使用、不推薦】 上述兩個接口均可以讓SpringBoot知道用戶配置的MyBatis映射關係在哪,除了用接口方式外,還能夠:
MapperFactoryBean
裝配MyBatis;MapperScannerConfigurer
;SqlSessionFactory
是SpringBoot自動生成好了,因此直接拿來使用);上面兩個接口可改爲以下代碼:(不經常使用、不推薦)
1. 經過MapperFactoryBean裝配MyBatis:
@Autowired SqlSessionFactory sqlSessionFactory = null; //定義一個MyBatis的Mapper接口 @Bean public MapperFactoryBean<MyBatisUserDao> initMyBatisUserDao(){ MapperFactoryBean<MyBatisUserDao> bean = new MapperFactoryBean<>(); bean.setMapperInterface(UserDAO.class); bean.setSessionFactory(sqlSessionFactory); return beam; }
2. 使用MapperScannerConfigurer:
@Bean public MapperScannerConfigurer mapperScannerConfig(){ //定義掃描器實例 MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); //加載SqlSessionFactory,SpringBoot會自動生產,SqlSessionFactory實例 mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory"); //定義掃描的包 mapperScannerConfigurer.setBeanPackage("com.dlhjw.mapper"); //限定被標註@Repository的接口才被掃描 mapperScannerConfigurer.setAnnotationClass(Repository.class); //經過繼承某個接口限制掃描,通常使用很少 //mapperScannerConfigurer.setMarkerInterface(....); return mapperScannerConfigurer; }
3. 使用MyBatis接口:
public interface MyBatisUserService{ public User getUser(Long id); }
@Service public class MyBatisUserServiceImpl implements MyBatisUserService{ //由於在啓動文件application.yaml配置了對應接口,因此直接依賴注入便可 @Autowired private MyBatisUserDao myBatisUserDao = null; @Override public User getUser(Long id){ return myBatisUserDao.getUser(id); } }
配置模式步驟以下。
1. 導入mybatis官方starter;
2. 編寫mapper接口,使用@Mapper
或@MapperScan
註解;
3. 配置全局配置文件(springboot自動配置好了);
在resources/mybatis/mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- 開啓駝峯命名匹配,或者在配置文件中配置 --> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration>
配置mybatis.configuration下面的全部,就是至關於改mybatis全局配置文件中的值;
mybatis: #注意:只能有一個全局配置,下面語句不能存在 # config-location: classpath:mybatis/mybatis-config.xml mapper-locations: classpath:mybatis/mapper/*.xml configuration: map-underscore-to-camel-case: true #推薦
4. 配置映射文件(編寫sql映射文件並綁定mapper接口);
使用Mapper接口綁定Xml
在resources/mybatis/mapper/AccountMapper.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"> <mapper namespace="com.dlhjw.admin.mapper.AccountMapper"> <!-- public Account getAcct(Long id) --> <select id="getAcct" resultType="com.dlhjw.admin.bean.Account"> select * from account_tbl where id=#{id} </select> </mapper>
註解模式步驟以下(自上而下分析,從數據層到表示層)。
1. 導入mybatis官方starter;
2. 編寫mapper接口,使用@Mapper
或@MapperScan
註解;
3. 接口的方法上標註@Select
註解,代替原來xml裏的<select>
標籤;
@Mapper public interface CityMapper { @Select("select * from city where id=#{id}") public City getById(Long id); }
4. 在service層裏編寫業務方法;
public interface CityService { City getById(Long id); }
@Service public class CityServiceImpl implements CityService { @Autowired CityMapper cityMapper; public City getById(Long id){ return cityMapper.getById(id); } }
5. 在Controller層裏編寫表示層相關方法;
*Controller相關知識參考下章。
@Controller public class IndexController { @Autowired CityService cityService; @ResponseBody @GetMapping("/city") public City getCityById(@RequestParam("id") Long id){ return cityService.getById(id); } }
混合模式步驟以下(自上而下分析,從數據層到表示層)。
1. 導入mybatis官方starter;
2. 編寫mapper接口,使用@Mapper
或@MapperScan
註解;
@Mapper public interface CityMapper { @Select("select * from city where id=#{id}") public City getById(Long id); public void insert(City city); }
3. 爲insert方法配置xml文件;
<mapper namespace="com.atguigu.admin.mapper.CityMapper"> <!-- useGeneratedKeys:使用自增主鍵,能夠返回自增主鍵值 keyProperty:自增屬性的id --> <insert id="insert" useGeneratedKeys="true" keyProperty="id"> insert into city(`name`,`state`,`country`) values(#{name},#{state},#{country}) </insert> </mapper>
4. 在service層裏編寫業務方法;
public interface CityService { City getById(Long id); void saveCity(City city); }
@Service public class CityServiceImpl implements CityService { @Autowired CityMapper cityMapper; public City getById(Long id){ return cityMapper.getById(id); } public void saveCity(City city) { counter.increment(); cityMapper.insert(city); } }
5. 在Controller層裏編寫表示層相關方法;
*Controller相關知識參考下章。
@Controller public class IndexController { @Autowired CityService cityService; @ResponseBody @PostMapping("/city") public City saveCity(City city){ cityService.saveCity(city); return city; } @ResponseBody @GetMapping("/city") public City getCityById(@RequestParam("id") Long id){ return cityService.getById(id); } }
6. *將上述insert
用註解方式改爲註解模式
*此步驟不是必要的。
@Mapper public interface CityMapper { @Insert("insert into city(`name`,`state`,`country`) values(#{name},#{state},#{country})") @Options(useGeneratedKeys = true,keyProperty = "id") public void insert(City city); }
useGeneratedKeys
表示使用自增主鍵,能夠返回自增主鍵值;keyProperty
表示自增屬性的id。SpringBoot能夠集成MyBatis插件完成一些複雜的功能,分頁插件相關配置以下。
1. 整合插件;
@Configuration public class MyBatisConfig { @Bean public MybatisPlusInterceptor paginationInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); // 設置請求的頁面大於最大頁後操做, true調回到首頁,false 繼續請求 默認false // paginationInterceptor.setOverflow(false); // 設置最大單頁限制數量,默認 500 條,-1 不受限制 // paginationInterceptor.setLimit(500); // 開啓 count 的 join 優化,只針對部分 left join //這是分頁攔截器 PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(); paginationInnerInterceptor.setOverflow(true); paginationInnerInterceptor.setMaxLimit(500L); mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor); return mybatisPlusInterceptor; } }
2. 編寫插件相關controller;
*Controller相關知識參考下章。
@GetMapping("/dynamic_table") public String dynamic_table(@RequestParam(value="pn",defaultValue = "1") Integer pn,Model model){ //構造分頁參數 Page<User> page = new Page<>(pn, 2); //調用page進行分頁 Page<User> userPage = userService.page(page, null); model.addAttribute("users",userPage); //重定向 return "table/dynamic_table"; }
SpringBoot整合MyBatis的方法以下:
mybatis-starter
;application.yaml
中,指定mapper-location
位置便可;Mapper
接口並標註@Mapper
註解;
mapper.xml
進行綁定映射;@MapperScan("com.dlhjw.admin.mapper")
簡化,其餘的接口就能夠不用標註@Mapper
註解。