SpringBoot 教程 & 笔记 |Demo04- 整合 MyBatis-Plus

本贴最后更新于 2293 天前,其中的信息可能已经渤澥桑田

本文主要讲解如何在springboot下整合mybatis-plus,并访问mysql数据库。

表结构

现有一张 User 表,其表结构如下:

id name age email
1 Jone 18 test1@baomidou.com
2 Jack 20 test2@baomidou.com
3 Tom 28 test3@baomidou.com
4 Sandy 21 test4@baomidou.com
5 Billie 24 test5@baomidou.com

其对应的数据库 Schema 脚本如下:

DROP TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT '主键ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年龄', email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱', PRIMARY KEY (id) );

其对应的数据库 Data 脚本如下:

DELETE FROM user; INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');

如果执行 delete 提示 Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect. 就先执行下 SET SQL_SAFE_UPDATES =0; 命令,接着就可以了!

创建工程

创建一个 Spring Boot 工程
参考 SpringBoot 教程&笔记 |Demo01-构建一个简单的 Web 应用程来创建

添加依赖

引入 mybatis-plus-boot-starterlombokmysql-connector-javafreemarkerswagger2 依赖:

<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.12</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> <scope>test</scope> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> </dependencies>

添加依赖

配置

application.yml 配置文件中添加 mysql 数据库的相关配置:

# DataSource Config spring: datasource: url: jdbc:mysql://localhost:3306/demo?useUnicode=yes&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai username: testuser password: driver-class-name: com.mysql.cj.jdbc.Driver

配置

代码生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Dao、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

package com.heardfate.springboot.demo; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.po.TableFill; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @program: springboot-demo04 * @since: 2018/10/23 * @author: Mr.HeardFate */ public class CodeGenerator { /** * 包名 */ private static final String PACKAGE_NAME = "com.heardfate.springboot.demo"; /** * 模块名称 */ private static final String MODULE_NAME = "demo04"; private static final String NAME = ""; /** * 输出文件的路径 */ private static final String OUT_PATH = System.getProperty("user.dir") + NAME + "/src/main/java"; /** * 输出文件的路径 */ private static final String OUT_PATH_MAPPING = System.getProperty("user.dir") + NAME + "/src/main/resources/mapper"; /** * 代码生成者 */ private static final String AUTHOR = "Heardfate"; /** * JDBC相关配置 */ private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&useSSL=false" + "&characterEncoding=UTF-8"; private static final String USER_NAME = "testuser"; private static final String PASSWORD = ""; /** * MySQL 生成演示 */ public static void main(String[] args) { // 自定义需要填充的字段 List tableFillList = new ArrayList(); //如 每张表都有一个创建时间、修改时间 //而且这基本上就是通用的了,新增时,创建时间和修改时间同时修改 //修改时,修改时间会修改, //虽然像Mysql数据库有自动更新几只,但像ORACLE的数据库就没有了, //使用公共字段填充功能,就可以实现,自动按场景更新了。 //如下是配置 //TableFill createField = new TableFill("gmt_create", FieldFill.INSERT); //TableFill modifiedField = new TableFill("gmt_modified", FieldFill.UPDATE); //tableFillList.add(createField); //tableFillList.add(modifiedField); // 代码生成器 AutoGenerator mpg = new AutoGenerator(); mpg.setGlobalConfig(// 全局配置 new GlobalConfig().setOutputDir(OUT_PATH)// 输出目录 .setFileOverride(true)// 是否覆盖文件 .setActiveRecord(true)// 开启 activeRecord 模式 .setEnableCache(false)// XML 二级缓存 .setBaseResultMap(false)// XML ResultMap .setBaseColumnList(true)// XML columList .setAuthor(AUTHOR)// 自定义文件命名,注意 %s 会自动填充表实体属性! .setXmlName("%sMapper") .setMapperName("%sDao") .setSwagger2(true) // .setServiceName("MP%sService") // .setServiceImplName("%sServiceDiy") // .setControllerName("%sAction") ); mpg.setDataSource(// 数据源配置 new DataSourceConfig().setDbType(DbType.MYSQL)// 数据库类型 .setDriverName(DRIVER).setUsername(USER_NAME).setPassword(PASSWORD).setUrl(URL)); mpg.setStrategy(// 策略配置 new StrategyConfig() // .setCapitalMode(true)// 全局大写命名 //.setTablePrefix(new String[]{"table_", "test_"})// 此处可以修改为您的表前缀 .setNaming(NamingStrategy.underline_to_camel)// 表名生成策略 .setColumnNaming(NamingStrategy.underline_to_camel) //.setLogicDeleteFieldName("is_delete") //逻辑删除字段 // .setInclude(new String[] {"user"}) // 需要生成的表 // .setExclude(new String[]{"test"}) // 排除生成的表 // 自定义实体,公共字段 //.setSuperEntityColumns(new String[]{"gmt_create", "gmt_modified", "create_user", "executor", "is_delete", "pass_key"}) //.setTableFillList(tableFillList)//和68行对应,设置公共填充字段 // 自定义实体父类 //.setSuperEntityClass("com.baomidou.demo.base.BsBaseEntity") // 自定义 mapper 父类 // .setSuperMapperClass("com.baomidou.demo.base.BsBaseMapper") // 自定义 service 父类 // .setSuperServiceClass("com.baomidou.demo.base.BsBaseService") // 自定义 service 实现类父类 // .setSuperServiceImplClass("com.baomidou.demo.base.BsBaseServiceImpl") // 自定义 controller 父类 // .setSuperControllerClass("com.baomidou.demo.TestController") // 【实体】是否生成字段常量(默认 false) // public static final String ID = "test_id"; .setEntityColumnConstant(true) // 【实体】是否为构建者模型(默认 false) // public User setName(String name) {this.name = name; return this;} .setEntityBuilderModel(true) // 【实体】是否为lombok模型(默认 false)document .setEntityLombokModel(true) // Boolean类型字段是否移除is前缀处理 .setEntityBooleanColumnRemoveIsPrefix(true) //生成 @RestController 控制器 .setRestControllerStyle(true) //驼峰转连字符 //.setControllerMappingHyphenStyle(true) ); mpg.setPackageInfo(// 包配置 new PackageConfig().setModuleName(MODULE_NAME).setParent(PACKAGE_NAME)// 自定义包路径 .setController("controller")// 这里是控制器包名,默认 web .setXml("mapper").setMapper("dao") ); mpg.setCfg( // 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值 new InjectionConfig() { @Override public void initMap() {}} .setFileOutConfigList( Collections.singletonList(new FileOutConfig("/templates/mapper.xml" + ".ftl") { // 自定义输出文件目录 @Override public String outputFile(TableInfo tableInfo) { return OUT_PATH_MAPPING + "/" + MODULE_NAME + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }))); mpg.setTemplate( // 关闭默认 xml 生成,调整生成 至 根目录 new TemplateConfig().setXml(null) // 自定义模板配置,模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy // 至您项目 src/main/resources/template 目录下,模板名称也可自定义如下配置: // .setController("..."); // .setEntity("..."); // .setMapper("..."); // .setXml("..."); // .setService("..."); // .setServiceImpl("..."); ); mpg.setTemplateEngine(new FreemarkerTemplateEngine()); // 执行生成 mpg.execute(); } }

运行 Main 方法后,自动生成对应代码
代码生成器
代码生成器

MybatisPlus 配置

现在,我们添加 MybatisPlus 配置类
src/main/java/com/heardfate/springboot/demo/demo04/config/MybatisPlusConfig

package com.heardfate.springboot.demo.demo04.config; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Configuration; /** * @since: 2018/10/23 * @author: Mr.HeardFate */ @Configuration @MapperScan("com.heardfate.springboot.demo.demo04.dao") public class MybatisPlusConfig { }

MybatisPlus 配置

开始使用

添加测试类,进行功能测试:

package com.heardfate.springboot.demo; import com.heardfate.springboot.demo.demo04.dao.UserDao; import com.heardfate.springboot.demo.demo04.entity.User; import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; /** * @since: 2018/10/23 * @author: Mr.HeardFate */ @RunWith(SpringRunner.class) @SpringBootTest public class SampleTest { @Autowired private UserDao userDao; @Test public void testSelect() { System.out.println(("----- selectAll method test ------")); List userList = userDao.selectList(null); Assert.assertEquals(5, userList.size()); userList.forEach(System.out::println); } }

测试通过获取到数据库数据

2018-10-23 20:25:05.172 INFO 2483 --- [ main] c.heardfate.springboot.demo.SampleTest : Started SampleTest in 9.063 seconds (JVM running for 10.273) ----- selectAll method test ------ User(id=1, name=Jone, age=18, email=test1@baomidou.com) User(id=2, name=Jack, age=20, email=test2@baomidou.com) User(id=3, name=Tom, age=28, email=test3@baomidou.com) User(id=4, name=Sandy, age=21, email=test4@baomidou.com) User(id=5, name=Billie, age=24, email=test5@baomidou.com) 2018-10-23 20:25:05.838 INFO 2483 --- [ Thread-1] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor' 2018-10-23 20:25:05.839 INFO 2483 --- [ Thread-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated... 2018-10-23 20:25:05.852 INFO 2483 --- [ Thread-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.

添加测试

BIGINT UNSIGNED 映射为 BigIntger(2018-11-03 更新)

以上配置,如果数据库有字段类型为 BIGINT UNSIGNED,自动映射为 LONG 类型,,通过设置,映射为 BigIntger
BIGINT ,BIGINT UNSIGNED。
如果不是无符号类型,BIGINT(20)的取值范围为-9223372036854775808~9223372036854775807。
与 Java.lang.Long 的取值范围完全一致,可映射为 Long;
而 BIGINT(20) UNSIGNED 的取值范围是 0 ~ 18446744073709551615,其中一半的数据超出了 Long 的取值范围,需将其映射为 BigInteger。

支持 BigInteger

更新后完整的代码生成器代码为:

package com.heardfate.springboot.demo; import com.baomidou.mybatisplus.annotation.DbType; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.config.*; import com.baomidou.mybatisplus.generator.config.po.TableFill; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * @program: springboot-demo04 * @since: 2018/10/23 * @author: Mr.HeardFate */ public class CodeGenerator { /** * 包名 */ private static final String PACKAGE_NAME = "com.heardfate.springboot.demo"; /** * 模块名称 */ private static final String MODULE_NAME = "demo04"; private static final String NAME = ""; /** * 输出文件的路径 */ private static final String OUT_PATH = System.getProperty("user.dir") + NAME + "/src/main/java"; /** * 输出文件的路径 */ private static final String OUT_PATH_MAPPING = System.getProperty("user.dir") + NAME + "/src/main/resources/mapper"; /** * 代码生成者 */ private static final String AUTHOR = "Heardfate"; /** * JDBC相关配置 */ private static final String DRIVER = "com.mysql.cj.jdbc.Driver"; private static final String URL = "jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&useSSL=false" + "&characterEncoding=UTF-8"; private static final String USER_NAME = "testuser"; private static final String PASSWORD = ""; /** * MySQL 生成演示 */ public static void main(String[] args) { // 自定义需要填充的字段 List tableFillList = new ArrayList(); //如 每张表都有一个创建时间、修改时间 //而且这基本上就是通用的了,新增时,创建时间和修改时间同时修改 //修改时,修改时间会修改, //虽然像Mysql数据库有自动更新几只,但像ORACLE的数据库就没有了, //使用公共字段填充功能,就可以实现,自动按场景更新了。 //如下是配置 //TableFill createField = new TableFill("gmt_create", FieldFill.INSERT); //TableFill modifiedField = new TableFill("gmt_modified", FieldFill.UPDATE); //tableFillList.add(createField); //tableFillList.add(modifiedField); // 代码生成器 AutoGenerator mpg = new AutoGenerator(); mpg.setGlobalConfig(// 全局配置 new GlobalConfig().setOutputDir(OUT_PATH)// 输出目录 .setFileOverride(true)// 是否覆盖文件 .setActiveRecord(true)// 开启 activeRecord 模式 .setEnableCache(false)// XML 二级缓存 .setBaseResultMap(false)// XML ResultMap .setBaseColumnList(true)// XML columList .setAuthor(AUTHOR)// 自定义文件命名,注意 %s 会自动填充表实体属性! .setXmlName("%sMapper") .setMapperName("%sDao") .setSwagger2(true) // .setServiceName("MP%sService") // .setServiceImplName("%sServiceDiy") // .setControllerName("%sAction") ); mpg.setDataSource(// 数据源配置 new DataSourceConfig().setDbType(DbType.MYSQL)// 数据库类型 .setDriverName(DRIVER).setUsername(USER_NAME).setPassword(PASSWORD).setUrl(URL) .setTypeConvert(new MySqlTypeConvert() { // 自定义数据库表字段类型转换【可选】 @Override public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) { System.out.println("待转换类型:" + fieldType); // 注意!!!processTypeConvert存在默认类型转换,如果不是你要的效果请自定义返回。 String t = fieldType.toLowerCase(); if (t.contains("unsigned")) { if (t.contains("bigint")) { return DbColumnType.BIG_INTEGER; }else{ System.err.println("I am not know!"); return super.processTypeConvert(globalConfig, fieldType); } }else{ return super.processTypeConvert(globalConfig, fieldType); } } }) ); mpg.setStrategy(// 策略配置 new StrategyConfig() // .setCapitalMode(true)// 全局大写命名 //.setTablePrefix(new String[]{"table_", "test_"})// 此处可以修改为您的表前缀 .setNaming(NamingStrategy.underline_to_camel)// 表名生成策略 .setColumnNaming(NamingStrategy.underline_to_camel) //.setLogicDeleteFieldName("is_delete") //逻辑删除字段 // .setInclude(new String[] {"user"}) // 需要生成的表 // .setExclude(new String[]{"test"}) // 排除生成的表 // 自定义实体,公共字段 //.setSuperEntityColumns(new String[]{"gmt_create", "gmt_modified", "create_user", "executor", "is_delete", "pass_key"}) //.setTableFillList(tableFillList)//和68行对应,设置公共填充字段 // 自定义实体父类 //.setSuperEntityClass("com.baomidou.demo.base.BsBaseEntity") // 自定义 mapper 父类 // .setSuperMapperClass("com.baomidou.demo.base.BsBaseMapper") // 自定义 service 父类 // .setSuperServiceClass("com.baomidou.demo.base.BsBaseService") // 自定义 service 实现类父类 // .setSuperServiceImplClass("com.baomidou.demo.base.BsBaseServiceImpl") // 自定义 controller 父类 // .setSuperControllerClass("com.baomidou.demo.TestController") // 【实体】是否生成字段常量(默认 false) // public static final String ID = "test_id"; .setEntityColumnConstant(true) // 【实体】是否为构建者模型(默认 false) // public User setName(String name) {this.name = name; return this;} .setEntityBuilderModel(true) // 【实体】是否为lombok模型(默认 false)document .setEntityLombokModel(true) // Boolean类型字段是否移除is前缀处理 .setEntityBooleanColumnRemoveIsPrefix(true) //生成 @RestController 控制器 .setRestControllerStyle(true) //驼峰转连字符 //.setControllerMappingHyphenStyle(true) ); mpg.setPackageInfo(// 包配置 new PackageConfig().setModuleName(MODULE_NAME).setParent(PACKAGE_NAME)// 自定义包路径 .setController("controller")// 这里是控制器包名,默认 web .setXml("mapper").setMapper("dao") ); mpg.setCfg( // 注入自定义配置,可以在 VM 中使用 cfg.abc 设置的值 new InjectionConfig() { @Override public void initMap() {}} .setFileOutConfigList( Collections.singletonList(new FileOutConfig("/templates/mapper.xml" + ".ftl") { // 自定义输出文件目录 @Override public String outputFile(TableInfo tableInfo) { return OUT_PATH_MAPPING + "/" + MODULE_NAME + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }))); mpg.setTemplate( // 关闭默认 xml 生成,调整生成 至 根目录 new TemplateConfig().setXml(null) // 自定义模板配置,模板可以参考源码 /mybatis-plus/src/main/resources/template 使用 copy // 至您项目 src/main/resources/template 目录下,模板名称也可自定义如下配置: // .setController("..."); // .setEntity("..."); // .setMapper("..."); // .setXml("..."); // .setService("..."); // .setServiceImpl("..."); ); mpg.setTemplateEngine(new FreemarkerTemplateEngine()); // 执行生成 mpg.execute(); } }

BIGINT UNSIGNED 插入报错问题(2018-11-09 更新)

如果数据库字段类型为 BIGINT UNSIGNED,映射为 BigIntger。获取数据会正常,添加数据会报错 Could not set property 'id' of 'class XXX.entity.User' with value '1060015479998566402' Cause: java.lang.IllegalArgumentException: argument type mismatch
因为没有指定 ID 生成策略,mybatis-plus 默认为 ID_WORKER,是 Long 类型!
所以指定为 BigIntger,可以通过手动设置 ID,如 bean.setId(new BigInteger(IdWorker.getIdStr()));
Issues:UNSIGNED BIGINT(20)映射问题

参考

MyBatis-Plus 快速开始
MyBatis-Plus 代码生成器

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    949 引用 • 1460 回帖 • 1 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 365 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    693 引用 • 537 回帖 • 1 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...