如何集成與使用Spring Boot + Mybatis-Plus,相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。
創(chuàng)新互聯(lián)是一家專注于成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站和四川服務(wù)器托管的網(wǎng)絡(luò)公司,有著豐富的建站經(jīng)驗(yàn)和案例。
當(dāng)Spring Boot應(yīng)用從主方法main()啟動(dòng)后,首先加載Spring Boot注解類@SpringBootApplication。
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
在該類里加載注解類@EnableAutoConfiguration。
在EnableAutoConfiguration類使用注解類@Import導(dǎo)入了AutoConfigurationImportSelector自動(dòng)配置選擇器類來加載其他可自動(dòng)配置的組件,步驟如下:
1、AutoConfigurationImportSelector自動(dòng)配置選擇器調(diào)用getCandidateConfigurations方法,方法中SpringFactoriesLoader類通過loadFactoryNames方法掃描獲取各jar包類路徑下的META-INF/spring.factories文件
2、將掃描到的META-INF/spring.factories文件封裝成Properties對(duì)象
3、遍歷Properties對(duì)象,從中取出屬性名org.springframework.boot.autoconfigure.EnableAutoConfiguration.EnableAutoConfiguration對(duì)應(yīng)的值,值就為當(dāng)前Jar包需Spring Boot加載的配置類,加載到容器中,并根據(jù)配置條件實(shí)例化配置類中的類對(duì)象
protected ListgetCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct."); return configurations; }
private static Map> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //掃描META-INF/spring.factories文件 Enumeration urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); //通過spring.factories文件Url封成Properties對(duì)象 Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry, ?> entry = (Entry)var6.next(); String factoryClassName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName, factoryName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
來看下mybatis-plus-boot-starter包下的META-INF/spring.factories文件
文件中只有一條配置屬性值,對(duì)應(yīng)的自動(dòng)配置類為MybatisPlusAutoConfiguration。至此,MyBatis-Plus是如何被自動(dòng)配置并加載容器介紹到這里,后續(xù)會(huì)講解Spring Boot時(shí)會(huì)更細(xì)致自動(dòng)配置原理,各位同伴們繼續(xù)關(guān)注。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration
了解Spring Boot是如何自動(dòng)配置MyBatis-Plus后,接下來講解使用MyBatis-Plus進(jìn)行通用的CRUD操作以及相關(guān)操作的配置。
上一章節(jié),我們準(zhǔn)備了一個(gè)sql腳本,執(zhí)行腳本后創(chuàng)建t_sys_log表,表結(jié)構(gòu)可以查看上一章節(jié)。接著我們?cè)陧?xiàng)目中創(chuàng)建對(duì)應(yīng)entity類和mapper接口
1. 目錄結(jié)構(gòu)如下
2. 實(shí)體類SysLog屬性如下
public class SysLog implements Serializable { private int logId; private Integer optionType; private String optionPerson; private String optionContent; private String optionIp; private String optionStatus; private String errorInfo; private Date optionTime; //get與set方法
3. 在SysLogMapper接口中繼承MyBatis-Plus包中BaseMapper接口,接口定義泛型,使用SysLog類
import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface SysLogMapper extends BaseMapper{ }
4. 注入mapper接口,需要將mapper實(shí)例到Spring容器中,在這三種方式
在Spring Boot主方法類上加上@MapperScan("com.banxun.demo.mapper"),配置mapper接口所在包路徑,自動(dòng)掃描此路徑下的mapper接口
@SpringBootApplication @MapperScan("com.banxun.demo.mapper") public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
直接在mapper接口上加入@Mapper注解
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; @Mapper public interface SysLogMapper extends BaseMapper{ }
在項(xiàng)目中新建config目錄,再新建MybatisConfig配置類,使用注解@Configuration定義此類為配置類,使用注解注解@Bean。容器啟動(dòng)時(shí),創(chuàng)建MapperScannerConfigurer對(duì)象,設(shè)置basePackage屬性值為mapper接口的包路徑
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class MybatisConfig { @Bean public MapperScannerConfigurer MapperScannerConfigurer(){ MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer(); scannerConfigurer.setBasePackage("com.banxun.demo.mapper"); return scannerConfigurer; } }
到此,MyBatis-Plus基本配置完成,我們來使用junit進(jìn)行測(cè)試,看看測(cè)試有什么問題,針對(duì)具體問題來解決。后續(xù)章節(jié)中對(duì)MyBatis-Plus其他配置一一進(jìn)行講解。
在junit測(cè)試類中注入SysLogMapper,編寫如下代碼插入一條日志記錄,執(zhí)行junit測(cè)試方法
@RunWith(SpringRunner.class) @SpringBootTest public class BootApplicationTests { @Autowired private SysLogMapper sysLogMapper; @Test public void contextLoads() { SysLog sysLog = new SysLog(); sysLog.setOptionTime(new Date()); sysLog.setOptionType(1); sysLog.setOptionContent("測(cè)試mybatis-plus"); sysLogMapper.insert(sysLog); } }
問題1: Error updating database. Cause: java.sql.SQLSyntaxErrorException: Table 'wechat.sys_log' doesn't exist
執(zhí)行完成控制臺(tái)輸出打印上面的異常信息,報(bào)sys_log表不存在,而我們創(chuàng)建的表名為t_sys_log,有前綴"t_"。在現(xiàn)在配置下,MyBatis-Plus默認(rèn)自動(dòng)按駝峰結(jié)構(gòu)類名進(jìn)行映射成帶下劃線_隔離的表名,解決此問題有兩種方法:
在實(shí)體類名SysLog上加@TableName注解指定映射表名
@TableName("t_sys_log") public class SysLog implements Serializable {
在配置文件application.properties添加全局配置屬性統(tǒng)一處理未注解指定表名實(shí)體類映射表名時(shí)加入前綴"t_"
mybatis-plus.global-config.db-config.table-prefix=t_
問題2: Cause: java.sql.SQLSyntaxErrorException: Unknown column 'log_id' in 'field list'
根據(jù)問題1配置完成后再次執(zhí)行junit測(cè)試方法,控制臺(tái)輸出打印上面的異常信息,報(bào)log_id列不存在。在t_sys_log表中,主鍵名為f_log_id,這里同樣缺少字段前綴,解決方法有兩種:
默認(rèn)MyBatis-Plus會(huì)根據(jù)屬性駝峰命名自動(dòng)進(jìn)行字段映射及主鍵名叫id都可無注解指定字段名
屬性名上加@TableField("字段名")注解指定映射字段名,主鍵字段使用@TableId("字段名")注解
通過配置文件application.properties添加全局配置屬性統(tǒng)一處理,%s對(duì)應(yīng)自動(dòng)映射字段名
mybatis-plus.global-config.db-config.column-format=f_%s
問題3:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: Could not set property 'logId' of 'class com.banxun.demo.entity.SysLog' with value '1164549971505057794' Cause: java.lang.IllegalArgumentException: argument type mismatch
配置完問題2后,控制臺(tái)輸出再次打印上面的異常信息。此問題原因是插入數(shù)據(jù)時(shí)MyBatis-Plus為主鍵生成的Id值過長(zhǎng),需要配置主鍵生成策略。這問題解決也有兩種方式:
在主鍵性加上@TableId(value = "f_log_id", type = IdType.AUTO),IdType有六個(gè)選項(xiàng)值,默認(rèn)ID_WORKER,我們表使用鍵值自動(dòng)遞增,所以選AUTO
public enum IdType { AUTO(0), //數(shù)據(jù)庫自增 NONE(1), //無狀態(tài) INPUT(2), //自行輸入 ID_WORKER(3), //分布式全局唯一ID 長(zhǎng)整型類型 UUID(4), //32位UUID字符串 ID_WORKER_STR(5); //分布式全局唯一ID 字符串類型
在配置文件application.properties添加全局配置屬性統(tǒng)一處理
mybatis-plus.global-config.db-config.id-type=auto
經(jīng)過前面的配置后,junit方法執(zhí)行成功,在庫中插入了一條日志記錄
根據(jù)id查詢
@Test public void contextLoads() { SysLog sysLog = sysLogMapper.selectById(173); System.out.println(sysLog.getOptionContent()); }
控制臺(tái)打印輸入前面插入的日志內(nèi)容信息
2019-08-22 23:16:00.489 INFO 5112 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. _ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.1.2 2019-08-22 23:16:00.867 INFO 5112 --- [ main] com.banxun.demo.DemoApplicationTests : Started DemoApplicationTests in 2.204 seconds (JVM running for 3.16) 測(cè)試mybatis-plus 2019-08-22 23:16:01.132 INFO 5112 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2019-08-22 23:16:01.317 INFO 5112 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
根據(jù)內(nèi)容模糊查詢,這使用QueryWrapper條件構(gòu)造器進(jìn)行條件查詢
@Test public void contextLoads() { QueryWrapperqueryWrapper = new QueryWrapper<>(); queryWrapper.like("f_option_content", "plus"); List sysLogs = sysLogMapper.selectList(queryWrapper); for (SysLog sysLog : sysLogs) { System.out.println(sysLog.getOptionContent()); } }
@Test public void contextLoads() { SysLog sysLog = new SysLog(); sysLog.setLogId(173); sysLog.setOptionContent("測(cè)試Spring Boot + MyBatis-Plus"); sysLogMapper.updateById(sysLog); }
執(zhí)行完成后,我們?cè)偻ㄟ^上面根據(jù)id查詢,可以看到控制臺(tái)打印輸入更新的日志內(nèi)容信息
2019-08-22 23:26:57.358 INFO 22964 --- [ main] com.banxun.demo.DemoApplicationTests : Starting DemoApplicationTests on LAPTOP-6AQTBBR1 with PID 22964 (started by karanatarm in E:\ideaplace\demo) 2019-08-22 23:26:57.359 INFO 22964 --- [ main] com.banxun.demo.DemoApplicationTests : No active profile set, falling back to default profiles: default 2019-08-22 23:26:58.369 INFO 22964 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2019-08-22 23:26:58.813 INFO 22964 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. _ _ |_ _ _|_. ___ _ | _ | | |\/|_)(_| | |_\ |_)||_|_\ / | 3.1.2 2019-08-22 23:26:59.167 INFO 22964 --- [ main] com.banxun.demo.DemoApplicationTests : Started DemoApplicationTests in 2.087 seconds (JVM running for 3.044) 測(cè)試Spring Boot + MyBatis-Plus 2019-08-22 23:26:59.456 INFO 22964 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2019-08-22 23:26:59.518 INFO 22964 --- [ Thread-2] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
@Test public void tes() { SysLog sysLog = new SysLog(); sysLog.setLogId(173); sysLogMapper.deleteById(sysLog); }
執(zhí)行完成后,我們?cè)俑鶕?jù)id查詢,可以看到控制臺(tái)沒有打印輸入日志內(nèi)容
看完上述內(nèi)容,你們掌握如何集成與使用Spring Boot + Mybatis-Plus的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!