本文将介绍MyBatis-Plus使用的详细情况,特别是关于mybatisplus用法的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于FluentM
本文将介绍MyBatis-Plus使用的详细情况,特别是关于mybatis plus 用法的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于Fluent Mybatis, 原生Mybatis, Mybatis Plus三者功能对比、Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比、idea springboot2 集成Mybatis使用mybatis-generator-plugin生成代码、java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】的知识。
本文目录一览:- MyBatis-Plus使用(mybatis plus 用法)
- Fluent Mybatis, 原生Mybatis, Mybatis Plus三者功能对比
- Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比
- idea springboot2 集成Mybatis使用mybatis-generator-plugin生成代码
- java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】
MyBatis-Plus使用(mybatis plus 用法)
一、MyBatis-Plus
1、简介
MyBatis-Plus 是一个 Mybatis 增强版工具,在 MyBatis 上扩充了其他功能没有改变其基本功能,为了简化开发提交效率而存在。
官网文档地址:
https://mp.baomidou.com/guide/
MyBatis-Plus 特性:
https://mp.baomidou.com/guide/#%E7%89%B9%E6%80%A7
2、使用 SpringBoot 快速使用 MyBatis-Plus
(1)准备工作
需要 Java 开发环境(JDK)以及相应的开发工具(IDE)。
需要 maven(用来下载相关依赖的 jar 包)。
需要 SpringBoot。
可以使用 IDEA 安装一个 mybatis-plus 插件。
(2)创建一个 SpringBoot 项目。
方式一:去官网 https://start.spring.io/ 初始化一个,然后导入 IDE 工具即可。
方式二:直接使用 IDE 工具创建一个。 Spring Initializer。
(3)添加 MyBatis-Plus 依赖(mybatis-plus-boot-starter)
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1.tmp</version> </dependency>
(4)为了测试开发,此处使用 MysqL 8,需要引入 MysqL 相关依赖。
为了简化代码,引入 lombok 依赖(减少 getter、setter 等方法)。
<dependency> <groupId>MysqL</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.18</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency>
(5)完整依赖文件(pom.xml)
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.lyh.test</groupId> <artifactId>test-mybatis-plus</artifactId> <version>0.0.1-SNAPSHOT</version> <name>test-mybatis-plus</name> <description>测试 -- 测试 MyBatis-Plus 功能</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1.tmp</version> </dependency> <dependency> <groupId>MysqL</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.18</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
(6)使用一个表进行测试。
仅供参考,可以定义 创建时间、修改时间等字段。
DROP DATABASE IF EXISTS testMyBatisPlus; CREATE DATABASE testMyBatisPlus; USE testMyBatisPlus; 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) ); 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');
(7)在 application.yml 文件中配置 MysqL 数据源信息。
spring: datasource: driver-class-name: com.MysqL.cj.jdbc.Driver username: root password: 123456 url: jdbc:MysqL://localhost:3306/testMyBatisPlus?useUnicode=true&characterEncoding=utf8
(8)编写表对应的 实体类。
package entity; import lombok.Data; @Data public class User { private Long id; private String name; private int age; private String email; }
(9)编写操作实体类的 Mapper 类。
直接继承 BaseMapper,这是 mybatis-plus 封装好的类。
package mapper; import bean.User; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface UserMapper extends BaseMapper<User> { }
service代码
package service; import com.baomidou.mybatisplus.extension.service.IService; import entity.User; /** * 用户Service */ public interface UserService extends IService<User> { } @Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService { }
(10)实体类、Mapper 类都写好了,就可以使用了。
Step1:先得在启动类里扫描 Mapper 类,即添加 @MapperScan 注解
package com.lyh.test.testmybatisplus; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("mapper") @SpringBootApplication public class TestMybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(TestMybatisPlusApplication.class, args); } }
Step2:写一个测试类测试一下。
package com.lyh.test.testmybatisplus; import bean.User; import mapper.UserMapper; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBoottest; import java.util.List; @SpringBoottest class TestMybatisPlusApplicationTests { @Autowired private UserMapper userMapper; @Test public void testSelect() { System.out.println(("----- selectAll method test ------")); List<User> userList = userMapper.selectList(null); for(User user:userList) { System.out.println(user); } } }
(11)总结:
通过以上简单操作,就能对 user 表进行 CRUD 操作,不需要去编写 xml 文件。
注:
若遇到 @Autowired 标记的变量出现 红色下划线,但是不影响 正常运行。
可以进入 Settings,找到 inspection,并选择其中的 Spring Core -> Code -> Autowiring for Bean Class,将 Error 改为 Warning,即可。
回到顶部
二、Mybatis-Plus 常用操作
1、配置日志
【参考地址(两种方式配置日志)】 https://blog.csdn.net/dfBeautifulLive/article/details/100700365
想要查看执行的 sql 语句,可以在 yml 文件中添加配置信息,如下。
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 配置扫描xml文件 mybatis-plus.mapper-locations=classpath*:**/xml/*Mapper.xml
如下图所示:执行时会打印出 sql 语句。
2、简单认识一下常用注解
【@TableName 】 @TableName 用于定义表名 注: 常用属性: value 用于定义表名 【@TableId】 @TableId 用于定义表的主键 注: 常用属性: value 用于定义主键字段名 type 用于定义主键类型(主键策略 IdType) 主键策略: IdType.AUTO 主键自增,系统分配,不需要手动输入 IdType.NONE 未设置主键 IdType.INPUT 需要自己输入 主键值。 IdType.ASSIGN_ID 系统分配 ID,用于数值型数据(Long,对应 MysqL 中 BIGINT 类型)。 IdType.ASSIGN_UUID 系统分配 UUID,用于字符串型数据(String,对应 MysqL 中 varchar(32) 类型)。 【@TableField】 @TableField 用于定义表的非主键字段。 注: 常用属性: value 用于定义非主键字段名 exist 用于指明是否为数据表的字段, true 表示是,false 为不是。 fill 用于指定字段填充策略(FieldFill)。 字段填充策略:(一般用于填充 创建时间、修改时间等字段) FieldFill.DEFAULT 默认不填充 FieldFill.INSERT 插入时填充 FieldFill.UPDATE 更新时填充 FieldFill.INSERT_UPDATE 插入、更新时填充。 【@TableLogic】 @TableLogic 用于定义表的字段进行逻辑删除(非物理删除) 注: 常用属性: value 用于定义未删除时字段的值 delval 用于定义删除时字段的值 【@Version】 @Version 用于字段实现乐观锁
3、代码生成器
(1)AutoGenerator 简介
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
与 mybatis 中的 mybatis-generator-core 类似。
(2)添加依赖
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.3.1.tmp</version> </dependency> <!-- 添加 模板引擎 依赖 --> <dependency> <groupId>org.apache.veLocity</groupId> <artifactId>veLocity-engine-core</artifactId> <version>2.2</version> </dependency>
(3)代码分析
Step1:
创建一个 代码生成器。用于生成代码。
此处不用修改。
// Step1:代码生成器 AutoGenerator mpg = new AutoGenerator();
Step2:
配置全局信息。指定代码输出路径,以及包名、作者等信息。
此处按需添加,projectPath 需要修改,setAuthor 需要修改。
// Step2:全局配置 GlobalConfig gc = new GlobalConfig(); // 填写代码生成的目录(需要修改) String projectPath = "E:\\myProject\\test\\test_mybatis_plus"; // 拼接出代码最终输出的目录 gc.setoutputDir(projectPath + "/src/main/java"); // 配置开发者信息(可选)(需要修改) gc.setAuthor("lyh"); // 配置是否打开目录,false 为不打开(可选) gc.setopen(false); // 实体属性 Swagger2 注解,添加 Swagger 依赖,开启 Swagger2 模式(可选) //gc.setSwagger2(true); // 重新生成文件时是否覆盖,false 表示不覆盖(可选) gc.setFileOverride(false); // 配置主键生成策略,此处为 ASSIGN_ID(可选) gc.setIdType(IdType.ASSIGN_ID); // 配置日期类型,此处为 ONLY_DATE(可选) gc.setDateType(DateType.ONLY_DATE); // 默认生成的 service 会有 I 前缀 gc.setServiceName("%sService"); mpg.setGlobalConfig(gc);
Step3:
配置数据源信息。用于指定 需要生成代码的 数据仓库、数据表。
setUrl、setDriverName、setUsername、setPassword 均需修改。
// Step3:数据源配置(需要修改) DataSourceConfig dsc = new DataSourceConfig(); // 配置数据库 url 地址 dsc.setUrl("jdbc:MysqL://localhost:3306/testMyBatisPlus?useUnicode=true&characterEncoding=utf8"); // dsc.setSchemaName("testMyBatisPlus"); // 可以直接在 url 中指定数据库名 // 配置数据库驱动 dsc.setDriverName("com.MysqL.cj.jdbc.Driver"); // 配置数据库连接用户名 dsc.setUsername("root"); // 配置数据库连接密码 dsc.setPassword("123456"); mpg.setDataSource(dsc);
Step4:
配置包信息。
setParent、setModuleName 均需修改。其余按需求修改.
// Step:4:包配置 PackageConfig pc = new PackageConfig(); // 配置父包名(需要修改) pc.setParent("com.lyh.test"); // 配置模块名(需要修改) pc.setModuleName("test_mybatis_plus"); // 配置 entity 包名 pc.setEntity("entity"); // 配置 mapper 包名 pc.setMapper("mapper"); // 配置 service 包名 pc.setService("service"); // 配置 controller 包名 pc.setController("controller"); mpg.setPackageInfo(pc);
Step5:
配置数据表映射信息。
setInclude 需要修改,其余按实际开发修改。
// Step5:策略配置(数据库表配置) StrategyConfig strategy = new StrategyConfig(); // 指定表名(可以同时操作多个表,使用 , 隔开)(需要修改) strategy.setInclude("test_mybatis_plus_user"); // 配置数据表与实体类名之间映射的策略 strategy.setNaming(NamingStrategy.underline_to_camel); // 配置数据表的字段与实体类的属性名之间映射的策略 strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 配置 lombok 模式 strategy.setEntityLombokModel(true); // 配置 rest 风格的控制器(@RestController) strategy.setRestControllerStyle(true); // 配置驼峰转连字符 strategy.setControllerMappingHyphenStyle(true); // 配置表前缀,生成实体时去除表前缀 // 此处的表名为 test_mybatis_plus_user,模块名为 test_mybatis_plus,去除前缀后剩下为 user。 strategy.setTablePrefix(pc.getModuleName() + "_"); mpg.setStrategy(strategy);
Step6:
执行代码生成操作。
此处不用修改。
// Step6:执行代码生成操作 mpg.execute();
完整配置如下:
package com.lyh.test.test_mybatis_plus; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.rules.DateType; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import org.junit.jupiter.api.Test; public class TestAutoGenerate { @Test public void autoGenerate() { // Step1:代码生成器 AutoGenerator mpg = new AutoGenerator(); // Step2:全局配置 GlobalConfig gc = new GlobalConfig(); // 填写代码生成的目录(需要修改) String projectPath = "E:\\myProject\\test\\test_mybatis_plus"; // 拼接出代码最终输出的目录 gc.setoutputDir(projectPath + "/src/main/java"); // 配置开发者信息(可选)(需要修改) gc.setAuthor("lyh"); // 配置是否打开目录,false 为不打开(可选) gc.setopen(false); // 实体属性 Swagger2 注解,添加 Swagger 依赖,开启 Swagger2 模式(可选) //gc.setSwagger2(true); // 重新生成文件时是否覆盖,false 表示不覆盖(可选) gc.setFileOverride(false); // 配置主键生成策略,此处为 ASSIGN_ID(可选) gc.setIdType(IdType.ASSIGN_ID); // 配置日期类型,此处为 ONLY_DATE(可选) gc.setDateType(DateType.ONLY_DATE); // 默认生成的 service 会有 I 前缀 gc.setServiceName("%sService"); mpg.setGlobalConfig(gc); // Step3:数据源配置(需要修改) DataSourceConfig dsc = new DataSourceConfig(); // 配置数据库 url 地址 dsc.setUrl("jdbc:MysqL://localhost:3306/testMyBatisPlus?useUnicode=true&characterEncoding=utf8"); // dsc.setSchemaName("testMyBatisPlus"); // 可以直接在 url 中指定数据库名 // 配置数据库驱动 dsc.setDriverName("com.MysqL.cj.jdbc.Driver"); // 配置数据库连接用户名 dsc.setUsername("root"); // 配置数据库连接密码 dsc.setPassword("123456"); mpg.setDataSource(dsc); // Step:4:包配置 PackageConfig pc = new PackageConfig(); // 配置父包名(需要修改) pc.setParent("com.lyh.test"); // 配置模块名(需要修改) pc.setModuleName("test_mybatis_plus"); // 配置 entity 包名 pc.setEntity("entity"); // 配置 mapper 包名 pc.setMapper("mapper"); // 配置 service 包名 pc.setService("service"); // 配置 controller 包名 pc.setController("controller"); mpg.setPackageInfo(pc); // Step5:策略配置(数据库表配置) StrategyConfig strategy = new StrategyConfig(); // 指定表名(可以同时操作多个表,使用 , 隔开)(需要修改) strategy.setInclude("test_mybatis_plus_user"); // 配置数据表与实体类名之间映射的策略 strategy.setNaming(NamingStrategy.underline_to_camel); // 配置数据表的字段与实体类的属性名之间映射的策略 strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 配置 lombok 模式 strategy.setEntityLombokModel(true); // 配置 rest 风格的控制器(@RestController) strategy.setRestControllerStyle(true); // 配置驼峰转连字符 strategy.setControllerMappingHyphenStyle(true); // 配置表前缀,生成实体时去除表前缀 // 此处的表名为 test_mybatis_plus_user,模块名为 test_mybatis_plus,去除前缀后剩下为 user。 strategy.setTablePrefix(pc.getModuleName() + "_"); mpg.setStrategy(strategy); // Step6:执行代码生成操作 mpg.execute(); } }
4、自动填充数据功能
(1)简介
添加、修改数据时,每次都会使用相同的方式进行填充。比如 数据的创建时间、修改时间等。
Mybatis-plus 支持自动填充这些字段的数据。
给之前的数据表新增两个字段:创建时间、修改时间。
CREATE TABLE test_mybatis_plus_user ( id BIGINT 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 '邮箱', create_time timestamp NULL DEFAULT NULL COMMENT '创建时间', update_time timestamp NULL DEFAULT NULL COMMENT '最后修改时间', PRIMARY KEY (id) );
并使用 代码生成器生成代码。
(2)未使用自动填充时
未使用 自动填充时,每次添加、修改数据都可以手动对其进行添加。
@SpringBoottest class TestMybatisPlusApplicationTests { @Autowired private UserService userService; @Test public void testUpdate() { User user = new User(); user.setName("tom").setAge(20).setEmail("tom@163.com"); // 手动添加数据 user.setCreateTime(new Date()).setUpdateTime(new Date()); if (userService.save(user)) { userService.list().forEach(System.out::println); } else { System.out.println("添加数据失败"); } } }
(3)使用自动填充功能。
Step1:
使用 @TableField 注解,标注需要进行填充的字段。
/** * 创建时间 */ @TableField(fill = FieldFill.INSERT) private Date createTime; /** * 最后修改时间 */ @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime;
Step2:
自定义一个类,实现 MetaObjectHandler 接口,并重写方法。
添加 @Component 注解,交给 Spring 去管理。
package com.lyh.test.test_mybatis_plus.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.util.Date; @Component public class MyMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject MetaObject) { this.strictInsertFill(MetaObject, "createTime", Date.class, new Date()); this.strictInsertFill(MetaObject, "updateTime", Date.class, new Date()); } @Override public void updateFill(MetaObject MetaObject) { this.strictUpdateFill(MetaObject, "updateTime", Date.class, new Date()); } }
Step3:
简单测试一下。
@Test public void testAutoFill() { User user = new User(); user.setName("tom").setAge(20).setEmail("tom@163.com"); if (userService.save(user)) { userService.list().forEach(System.out::println); } else { System.out.println("添加数据失败"); } }
5、逻辑删除
(1)简介
删除数据,可以通过物理删除,也可以通过逻辑删除。
物理删除指的是直接将数据从数据库中删除,不保留。
逻辑删除指的是修改数据的某个字段,使其表示为已删除状态,而非删除数据,保留该数据在数据库中,但是查询时不显示该数据(查询时过滤掉该数据)。
给数据表增加一个字段:delete_flag,用于表示该数据是否被逻辑删除。
CREATE TABLE test_mybatis_plus_user ( id BIGINT 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 '邮箱', create_time timestamp NULL DEFAULT NULL COMMENT '创建时间', update_time timestamp NULL DEFAULT NULL COMMENT '最后修改时间', delete_flag tinyint(1) NULL DEFAULT NULL COMMENT '逻辑删除(0 未删除、1 删除)', PRIMARY KEY (id) );
(2)使用逻辑删除。
可以定义一个自动填充规则,初始值为 0。0 表示未删除, 1 表示删除。
/** * 逻辑删除(0 未删除、1 删除) */ @TableLogic(value = "0", delval = "1") @TableField(fill = FieldFill.INSERT) private Integer deleteFlag; @Override public void insertFill(MetaObject MetaObject) { this.strictInsertFill(MetaObject, "deleteFlag", Integer.class, 0); }
(3)简单测试
使用 mybatis-plus 封装好的方法时,会自动添加逻辑删除的功能。
若是自定义的 sql 语句,需要手动添加逻辑。
@Test public void testDelete() { if (userService.removeById(1258924257048547329L)) { System.out.println("删除数据成功"); userService.list().forEach(System.out::println); } else { System.out.println("删除数据失败"); } }
现有数据
执行 testDelete 进行逻辑删除。
若去除 TableLogic 注解,再执行 testDelete 时进行物理删除,直接删除这条数据。
6、分页插件的使用
(1)简介
与 mybatis 的插件 pageHelper 用法类似。
通过简单的配置即可使用。
(2)使用
Step1:
配置分页插件。
编写一个 配置类,内部使用 @Bean 注解将 PaginationInterceptor 交给 Spring 容器管理。
package com.lyh.test.test_mybatis_plus.config; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * 自定义一个配置类,mapper 扫描也可在此写上 */ @Configuration @MapperScan("com.lyh.test.test_mybatis_plus.mapper") public class Myconfig { /** * 分页插件 * @return 分页插件的实例 */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }
Step2:
编写分页代码。
直接 new 一个 Page 对象,对象需要传递两个参数(当前页,每页显示的条数)。
调用 mybatis-plus 提供的分页查询方法,其会将 分页查询的数据封装到 Page 对象中。
@Test public void testPage() { // Step1:创建一个 Page 对象 Page<User> page = new Page<>(); // Page<User> page = new Page<>(2, 5); // Step2:调用 mybatis-plus 提供的分页查询方法 userService.page(page, null); // Step3:获取分页数据 System.out.println(page.getCurrent()); // 获取当前页 System.out.println(page.getTotal()); // 获取总记录数 System.out.println(page.getSize()); // 获取每页的条数 System.out.println(page.getRecords()); // 获取每页数据的集合 System.out.println(page.getPages()); // 获取总页数 System.out.println(page.hasNext()); // 是否存在下一页 System.out.println(page.hasPrevIoUs()); // 是否存在上一页 }
7、乐观锁的实现
(1)首先认识一下 读问题、写问题?
操作数据库数据时,遇到的最基本问题就是 读问题与写问题。
读问题 指的是从数据库中读取数据时遇到的问题,比如:脏读、幻读、不可重复读。
【脏读、幻读、不可重复读 参考地址:】 https://www.cnblogs.com/l-y-h/p/12458777.html#_label0_3
写问题 指的是数据写入数据库时遇到的问题,比如:丢失更新(多个线程同时对某条数据更新,无论执行顺序如何,都会丢失其他线程更新的数据)
(2)如何解决写问题?
乐观锁、悲观锁就是为了解决 写问题而存在的。
乐观锁:总是假设最好的情况,每次读取数据时认为数据不会被修改(即不加锁),当进行更新操作时,会判断这条数据是否被修改,未被修改,则进行更新操作。若被修改,则数据更新失败,可以对数据进行重试(重新尝试修改数据)。
悲观锁:总是假设最坏的情况,每次读取数据时认为数据会被修改(即加锁),当进行更新操作时,直接更新数据,结束操作后释放锁(此处才可以被其他线程读取)。
(3)乐观锁、悲观锁使用场景?
乐观锁一般用于读比较多的场合,尽量减少加锁的开销。
悲观锁一般用于写比较多的场合,尽量减少 类似 乐观锁重试更新引起的性能开销。
(4)乐观锁两种实现方式
方式一:通过版本号机制实现。
在数据表中增加一个 version 字段。
取数据时,获取该字段,更新时以该字段为条件进行处理(即set version = newVersion where version = oldVersion),若 version 相同,则更新成功(给新 version 赋一个值,一般加 1)。若 version 不同,则更新失败,可以重新尝试更新操作。
方式二:通过 CAS 算法实现。
CAS 为 Compare And Swap 的缩写,即比较交换,是一种无锁算法(即在不加锁的情况实现多线程之间的变量同步)。
CAS 操作包含三个操作数 —— 内存值(V)、预期原值(A)和新值(B)。如果内存地址里面的值 V 和 A 的值是一样的,那么就将内存里面的值更新成B。若 V 与 A 不一致,则不执行任何操作(可以通过自旋操作,不断尝试修改数据直至成功修改)。即 V == A ? V = B : V = V。
CAS 可能导致 ABA 问题(两次读取数据时值相同,但不确定值是否被修改过),比如两个线程操作同一个变量,线程 A、线程B 初始读取数据均为 A,后来 线程B 将数据修改为 B,然后又修改为 A,此时线程 A 再次读取到的数据依旧是 A,虽然值相同但是中间被修改过,这就是 ABA 问题。可以加一个额外的标志位 C,用于表示数据是否被修改。当标志位 C 与预期标志位相同、且 V == A 时,则更新值 B。
(5)mybatis-plus 实现乐观锁(通过 version 机制)
实现思路:
Step1:取出记录时,获取当前version
Step2:更新时,带上这个version
Step3:执行更新时, set version = newVersion where version = oldVersion
Step4:如果version不对,就更新失败
(6)mybatis-plus 代码实现乐观锁
Step1:
配置乐观锁插件。
编写一个配置类(可以与上例的分页插件共用一个配置类),将 OptimisticLockerInterceptor 通过 @Bean 交给 Spring 管理。
/** * 乐观锁插件 * @return 乐观锁插件的实例 */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); }
Step2:
定义一个数据库字段 version。
CREATE TABLE test_mybatis_plus_user ( id BIGINT 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 '邮箱', create_time timestamp NULL DEFAULT NULL COMMENT '创建时间', update_time timestamp NULL DEFAULT NULL COMMENT '最后修改时间', delete_flag tinyint(1) NULL DEFAULT NULL COMMENT '逻辑删除(0 未删除、1 删除)', version int NULL DEFAULT NULL COMMENT '版本号(用于乐观锁, 默认为 1)', PRIMARY KEY (id) );
Step3:
使用 @Version 注解标注对应的实体类。
可以通过 @TableField 进行数据自动填充。
/** * 版本号(用于乐观锁, 默认为 1) */ @Version @TableField(fill = FieldFill.INSERT) private Integer version; @Override public void insertFill(MetaObject MetaObject) { this.strictInsertFill(MetaObject, "version", Integer.class, 1); }
Step4:
简单测试一下,可以看一下 控制台 打印的 sql 语句。
@Test public void testVersion() { User user = new User(); user.setName("tom").setAge(20).setEmail("tom@163.com"); userService.save(user); userService.list().forEach(System.out::println); user.setName("jarry"); userService.update(user, null); userService.list().forEach(System.out::println); }
回到顶部
三、Mybatis-Plus CRUD 操作简单了解一下
1、Mapper 接口方法(CRUD)简单了解一下
(1)简介
使用代码生成器生成的 mapper 接口中,其继承了 BaseMapper 接口。
而 BaseMapper 接口中封装了一系列 CRUD 常用操作,可以直接使用,而不用自定义 xml 与 sql 语句进行 CRUD 操作(当然根据实际开发需要,自定义 sql 还是有必要的)。
此处简单介绍一下 BaseMapper 接口中的常用方法。
(2)方法介绍
混个眼熟,用多了就记得了。
【添加数据:(增)】 int insert(T entity); // 插入一条记录 注: T 表示任意实体类型 entity 表示实体对象 【删除数据:(删)】 int deleteById(Serializable id); // 根据主键 ID 删除 int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 根据 map 定义字段的条件删除 int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper); // 根据实体类定义的 条件删除对象 int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 进行批量删除 注: id 表示 主键 ID columnMap 表示表字段的 map 对象 wrapper 表示实体对象封装操作类,可以为 null。 idList 表示 主键 ID 集合(列表、数组),不能为 null 或 empty 【修改数据:(改)】 int updateById(@Param(Constants.ENTITY) T entity); // 根据 ID 修改实体对象。 int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); // 根据 updateWrapper 条件修改实体对象 注: update 中的 entity 为 set 条件,可以为 null。 updateWrapper 表示实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) 【查询数据:(查)】 T selectById(Serializable id); // 根据 主键 ID 查询数据 List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 进行批量查询 List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 根据表字段条件查询 T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据实体类封装对象 查询一条记录 Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询记录的总条数 List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 entity 集合) List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 map 集合) List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(但只保存第一个字段的值) <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 entity 集合),分页 <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 map 集合),分页 注: queryWrapper 表示实体对象封装操作类(可以为 null) page 表示分页查询条件
2、Service 接口方法(CRUD)简单了解一下
(1)简介
使用 代码生成器 生成的 service 接口中,其继承了 IService 接口。
IService 内部进一步封装了 BaseMapper 接口的方法(当然也提供了更详细的方法)。
使用时,可以通过 生成的 mapper 类进行 CRUD 操作,也可以通过 生成的 service 的实现类进行 CRUD 操作。(当然,自定义代码执行也可)
此处简单介绍一下 IService 中封装的常用方法。
(2)方法介绍
混个眼熟,用多了就记得了。
内部封装了 BaseMapper 的方法,也提供了新的方法。
比如:
添加了 批量更新 方法、更新或修改方法等。
对 查询方法 做了细化,使用 get 命名的方法查询一条数据,使用 list 命名的方法查询多条数据等。
增加了链式调用的方法。
【添加数据:(增)】 default boolean save(T entity); // 调用 BaseMapper 的 insert 方法,用于添加一条数据。 boolean saveBatch(Collection<T> entityList, int batchSize); // 批量插入数据 注: entityList 表示实体对象集合 batchSize 表示一次批量插入的数据量,默认为 1000 【添加或修改数据:(增或改)】 boolean saveOrUpdate(T entity); // id 若存在,则修改, id 不存在则新增数据 default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper); // 先根据条件尝试更新,然后再执行 saveOrUpdate 操作 boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize); // 批量插入并修改数据 【删除数据:(删)】 default boolean removeById(Serializable id); // 调用 BaseMapper 的 deleteById 方法,根据 id 删除数据。 default boolean removeByMap(Map<String, Object> columnMap); // 调用 BaseMapper 的 deleteByMap 方法,根据 map 定义字段的条件删除 default boolean remove(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 delete 方法,根据实体类定义的 条件删除对象。 default boolean removeByIds(Collection<? extends Serializable> idList); // 用 BaseMapper 的 deleteBatchIds 方法, 进行批量删除。 【修改数据:(改)】 default boolean updateById(T entity); // 调用 BaseMapper 的 updateById 方法,根据 ID 选择修改。 default boolean update(T entity, Wrapper<T> updateWrapper); // 调用 BaseMapper 的 update 方法,根据 updateWrapper 条件修改实体对象。 boolean updateBatchById(Collection<T> entityList, int batchSize); // 批量更新数据 【查找数据:(查)】 default T getById(Serializable id); // 调用 BaseMapper 的 selectById 方法,根据 主键 ID 返回数据。 default List<T> listByIds(Collection<? extends Serializable> idList); // 调用 BaseMapper 的 selectBatchIds 方法,批量查询数据。 default List<T> listByMap(Map<String, Object> columnMap); // 调用 BaseMapper 的 selectByMap 方法,根据表字段条件查询 default T getone(Wrapper<T> queryWrapper); // 返回一条记录(实体类保存)。 Map<String, Object> getMap(Wrapper<T> queryWrapper); // 返回一条记录(map 保存)。 default int count(Wrapper<T> queryWrapper); // 根据条件返回 记录数。 default List<T> list(); // 返回所有数据。 default List<T> list(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectList 方法,查询所有记录(返回 entity 集合)。 default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectMaps 方法,查询所有记录(返回 map 集合)。 default List<Object> listObjs(); // 返回全部记录,但只返回第一个字段的值。 default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectPage 方法,分页查询 default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectMapsPage 方法,分页查询 注: get 用于返回一条记录。 list 用于返回多条记录。 count 用于返回记录总数。 page 用于分页查询。 【链式调用:】 default QueryChainWrapper<T> query(); // 普通链式查询 default LambdaQueryChainWrapper<T> lambdaQuery(); // 支持 Lambda 表达式的修改 default UpdateChainWrapper<T> update(); // 普通链式修改 default LambdaUpdateChainWrapper<T> lambdaUpdate(); // 支持 Lambda 表达式的修改 注: query 表示查询 update 表示修改 Lambda 表示内部支持 Lambda 写法。 形如: query().eq("column", value).one(); lambdaQuery().eq(Entity::getId, value).list(); update().eq("column", value).remove(); lambdaUpdate().eq(Entity::getId, value).update(entity);
3、条件构造器(Wrapper,定义 where 条件)
(1)简介
上面介绍的 接口方法的参数中,会出现各种 wrapper,比如 queryWrapper、updateWrapper 等。wrapper 的作用就是用于定义各种各样的查询条件(where)。
Wrapper 条件构造抽象类 -- AbstractWrapper 查询条件封装,用于生成 sql 中的 where 语句。 -- QueryWrapper Entity 对象封装操作类,用于查询。 -- UpdateWrapper Update 条件封装操作类,用于更新。 -- AbstractLambdaWrapper 使用 Lambda 表达式封装 wrapper -- LambdaQueryWrapper 使用 Lambda 语法封装条件,用于查询。 -- LambdaUpdateWrapper 使用 Lambda 语法封装条件,用于更新。
(2)常用条件
参考源码以及官方文档总结的,还是一句话,混个眼熟,多用用就熟练了。
【通用条件:】 【比较大小: ( =, <>, >, >=, <, <= )】 eq(R column, Object val); // 等价于 =,例: eq("name", "老王") ---> name = '老王' ne(R column, Object val); // 等价于 <>,例: ne("name", "老王") ---> name <> '老王' gt(R column, Object val); // 等价于 >,例: gt("name", "老王") ---> name > '老王' ge(R column, Object val); // 等价于 >=,例: ge("name", "老王") ---> name >= '老王' lt(R column, Object val); // 等价于 <,例: lt("name", "老王") ---> name < '老王' le(R column, Object val); // 等价于 <=,例: le("name", "老王") ---> name <= '老王' 【范围:(between、not between、in、not in)】 between(R column, Object val1, Object val2); // 等价于 between a and b, 例: between("age", 18, 30) ---> age between 18 and 30 notBetween(R column, Object val1, Object val2); // 等价于 not between a and b, 例: notBetween("age", 18, 30) ---> age not between 18 and 30 in(R column, Object... values); // 等价于 字段 IN (v0, v1, ...),例: in("age",{1,2,3}) ---> age in (1,2,3) notin(R column, Object... values); // 等价于 字段 NOT IN (v0, v1, ...), 例: notin("age",{1,2,3}) ---> age not in (1,2,3) insql(R column, Object... values); // 等价于 字段 IN (sql 语句), 例: insql("id", "select id from table where id < 3") ---> id in (select id from table where id < 3) notinsql(R column, Object... values); // 等价于 字段 NOT IN (sql 语句) 【模糊匹配:(like)】 like(R column, Object val); // 等价于 LIKE '%值%',例: like("name", "王") ---> name like '%王%' notLike(R column, Object val); // 等价于 NOT LIKE '%值%',例: notLike("name", "王") ---> name not like '%王%' likeLeft(R column, Object val); // 等价于 LIKE '%值',例: likeLeft("name", "王") ---> name like '%王' likeRight(R column, Object val); // 等价于 LIKE '值%',例: likeRight("name", "王") ---> name like '王%' 【空值比较:(isNull、isNotNull)】 isNull(R column); // 等价于 IS NULL,例: isNull("name") ---> name is null isNotNull(R column); // 等价于 IS NOT NULL,例: isNotNull("name") ---> name is not null 【分组、排序:(group、having、order)】 groupBy(R... columns); // 等价于 GROUP BY 字段, ..., 例: groupBy("id", "name") ---> group by id,name orderByAsc(R... columns); // 等价于 ORDER BY 字段, ... ASC, 例: orderByAsc("id", "name") ---> order by id ASC,name ASC orderByDesc(R... columns); // 等价于 ORDER BY 字段, ... DESC, 例: orderByDesc("id", "name") ---> order by id DESC,name DESC having(String sqlHaving, Object... params); // 等价于 HAVING ( sql语句 ), 例: having("sum(age) > {0}", 11) ---> having sum(age) > 11 【拼接、嵌套 sql:(or、and、nested、apply)】 or(); // 等价于 a or b, 例:eq("id",1).or().eq("name","老王") ---> id = 1 or name = '老王' or(Consumer<Param> consumer); // 等价于 or(a or/and b),or 嵌套。例: or(i -> i.eq("name", "李白").ne("status", "活着")) ---> or (name = '李白' and status <> '活着') and(Consumer<Param> consumer); // 等价于 and(a or/and b),and 嵌套。例: and(i -> i.eq("name", "李白").ne("status", "活着")) ---> and (name = '李白' and status <> '活着') nested(Consumer<Param> consumer); // 等价于 (a or/and b),普通嵌套。例: nested(i -> i.eq("name", "李白").ne("status", "活着")) ---> (name = '李白' and status <> '活着') apply(String applysql, Object... params); // 拼接sql(若不使用 params 参数,可能存在 sql 注入),例: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08") ---> date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'") last(String lastsql); // 无视优化规则直接拼接到 sql 的最后,可能存若在 sql 注入。 exists(String existssql); // 拼接 exists 语句。例: exists("select id from table where age = 1") ---> exists (select id from table where age = 1) 【QueryWrapper 条件:】 select(String... sqlSelect); // 用于定义需要返回的字段。例: select("id", "name", "age") ---> select id, name, age select(Predicate<TableFieldInfo> predicate); // Lambda 表达式,过滤需要的字段。 lambda(); // 返回一个 LambdaQueryWrapper 【UpdateWrapper 条件:】 set(String column, Object val); // 用于设置 set 字段值。例: set("name", null) ---> set name = null etsql(String sql); // 用于设置 set 字段值。例: setsql("name = '老李头'") ---> set name = '老李头' lambda(); // 返回一个 LambdaUpdateWrapper
(3)简单使用,测试一下 QueryWrapper
@Test public void testQueryWrapper() { // Step1:创建一个 QueryWrapper 对象 QueryWrapper<User> queryWrapper = new QueryWrapper<>(); // Step2: 构造查询条件 queryWrapper .select("id", "name", "age") .eq("age", 20) .like("name", "j"); // Step3:执行查询 userService .list(queryWrapper) .forEach(System.out::println); }
当前数据库数据如下:
执行测试方法输出如下:
踩坑:
程序跑起来,在调用某个xml配置的方法时,报找不到xml中配置方法的错误。
后来经过排查,才发现是因为我在项目中使用了mybatis-plus,而mybatis-plus中的MybatisPlusAutoConfiguration覆盖了mybatis的MybatisAutoConfiguration。
解决办法:
通过将application.properties中的
mybatis.mapper-locations=classpath*:*Mapper.xml # 修改为 mybatis-plus.mapper-locations=classpath*:*Mapper.xml
转载链接:https://www.cnblogs.com/l-y-h/p/12859477.html
一、MyBatis-Plus 1、简介 2、使用 SpringBoot 快速使用 MyBatis-Plus 二、Mybatis-Plus 常用操作 1、配置日志 2、简单认识一下常用注解 3、代码生成器 4、自动填充数据功能 5、逻辑删除 6、分页插件的使用 7、乐观锁的实现 三、Mybatis-Plus CRUD 操作简单了解一下 1、Mapper 接口方法(CRUD)简单了解一下 2、Service 接口方法(CRUD)简单了解一下 3、条件构造器(Wrapper,定义 where 条件) 踩坑: 解决办法:
Fluent Mybatis, 原生Mybatis, Mybatis Plus三者功能对比
使用fluent mybatis可以不用写具体的xml文件,通过java api可以构造出比较复杂的业务sql语句,做到代码逻辑和sql逻辑的合一。不再需要在Dao中组装查询或更新操作,在xml或mapper中再组装参数。那对比原生Mybatis, Mybatis Plus或者其他框架,FluentMybatis提供了哪些便利呢?
需求场景设置
我们通过一个比较典型的业务需求来具体实现和对比下,假如有学生成绩表结构如下:
create table `student_score`
(
id bigint auto_increment comment ''主键ID'' primary key,
student_id bigint not null comment ''学号'',
gender_man tinyint default 0 not null comment ''性别, 0:女; 1:男'',
school_term int null comment ''学期'',
subject varchar(30) null comment ''学科'',
score int null comment ''成绩'',
gmt_create datetime not null comment ''记录创建时间'',
gmt_modified datetime not null comment ''记录最后修改时间'',
is_deleted tinyint default 0 not null comment ''逻辑删除标识''
) engine = InnoDB default charset=utf8;
现在有需求:
统计2000年三门学科(''英语'', ''数学'', ''语文'')及格分数按学期,学科统计最低分,最高分和平均分, 且样本数需要大于1条,统计结果按学期和学科排序
我们可以写SQL语句如下
select school_term,
subject,
count(score) as count,
min(score) as min_score,
max(score) as max_score,
avg(score) as max_score
from student_score
where school_term >= 2000
and subject in (''英语'', ''数学'', ''语文'')
and score >= 60
and is_deleted = 0
group by school_term, subject
having count(score) > 1
order by school_term, subject;
那上面的需求,分别用fluent mybatis, 原生mybatis 和 Mybatis plus来实现一番。
三者实现对比
使用fluent mybatis 来实现上面的功能
我们可以看到fluent api的能力,以及IDE对代码的渲染效果。
换成mybatis原生实现效果
- 定义Mapper接口
public interface MyStudentScoreMapper {
List<Map<String, Object>> summaryScore(SummaryQuery paras);
}
- 定义接口需要用到的参数实体 SummaryQuery
@Data
@Accessors(chain = true)
public class SummaryQuery {
private Integer schoolTerm;
private List<String> subjects;
private Integer score;
private Integer minCount;
}
- 定义实现业务逻辑的mapper xml文件
<select id="summaryScore" resultType="map" parameterType="cn.org.fluent.mybatis.springboot.demo.mapper.SummaryQuery">
select school_term,
subject,
count(score) as count,
min(score) as min_score,
max(score) as max_score,
avg(score) as max_score
from student_score
where school_term >= #{schoolTerm}
and subject in
<foreach collection="subjects" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
and score >= #{score}
and is_deleted = 0
group by school_term, subject
having count(score) > #{minCount}
order by school_term, subject
</select>
- 实现业务接口(这里是测试类, 实际应用中应该对应Dao类)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = QuickStartApplication.class)
public class MybatisDemo {
@Autowired
private MyStudentScoreMapper mapper;
@Test
public void mybatis_demo() {
// 构造查询参数
SummaryQuery paras = new SummaryQuery()
.setSchoolTerm(2000)
.setSubjects(Arrays.asList("英语", "数学", "语文"))
.setScore(60)
.setMinCount(1);
List<Map<String, Object>> summary = mapper.summaryScore(paras);
System.out.println(summary);
}
}
总之,直接使用mybatis,实现步骤还是相当的繁琐,效率太低。那换成mybatis plus的效果怎样呢?
换成mybatis plus实现效果
mybatis plus的实现比mybatis会简单比较多,实现效果如下
如红框圈出的,写mybatis plus实现用到了比较多字符串的硬编码(可以用Entity的get lambda方法部分代替字符串编码)。字符串的硬编码,会给开发同学造成不小的使用门槛,个人觉的主要有2点:
- 字段名称的记忆和敲码困难
- Entity属性跟随数据库字段发生变更后的运行时错误
其他框架,比如TkMybatis在封装和易用性上比mybatis plus要弱,就不再比较了。
生成代码编码比较
fluent mybatis生成代码设置
public class AppEntityGenerator {
static final String url = "jdbc:mysql://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";
public static void main(String[] args) {
FileGenerator.build(Abc.class);
}
@Tables(
/** 数据库连接信息 **/
url = url, username = "root", password = "password",
/** Entity类parent package路径 **/
basePack = "cn.org.fluent.mybatis.springboot.demo",
/** Entity代码源目录 **/
srcDir = "spring-boot-demo/src/main/java",
/** Dao代码源目录 **/
daoDir = "spring-boot-demo/src/main/java",
/** 如果表定义记录创建,记录修改,逻辑删除字段 **/
gmtCreated = "gmt_create", gmtModified = "gmt_modified", logicDeleted = "is_deleted",
/** 需要生成文件的表 ( 表名称:对应的Entity名称 ) **/
tables = @Table(value = {"student_score"})
)
static class Abc {
}
}
mybatis plus代码生成设置
public class CodeGenerator {
static String dbUrl = "jdbc:mysql://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8";
@Test
public void generateCode() {
GlobalConfig config = new GlobalConfig();
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL)
.setUrl(dbUrl)
.setUsername("root")
.setPassword("password")
.setDriverName(Driver.class.getName());
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig
.setCapitalMode(true)
.setEntityLombokModel(false)
.setNaming(NamingStrategy.underline_to_camel)
.setColumnNaming(NamingStrategy.underline_to_camel)
.setEntityTableFieldAnnotationEnable(true)
.setFieldPrefix(new String[]{"test_"})
.setInclude(new String[]{"student_score"})
.setLogicDeleteFieldName("is_deleted")
.setTableFillList(Arrays.asList(
new TableFill("gmt_create", FieldFill.INSERT),
new TableFill("gmt_modified", FieldFill.INSERT_UPDATE)));
config
.setActiveRecord(false)
.setIdType(IdType.AUTO)
.setOutputDir(System.getProperty("user.dir") + "/src/main/java/")
.setFileOverride(true);
new AutoGenerator().setGlobalConfig(config)
.setDataSource(dataSourceConfig)
.setStrategy(strategyConfig)
.setPackageInfo(
new PackageConfig()
.setParent("com.mp.demo")
.setController("controller")
.setEntity("entity")
).execute();
}
}
FluentMybatis特性一览
三者对比总结
看完3个框架对同一个功能点的实现, 各位看官肯定会有自己的判断,笔者这里也总结了一份比较。
- | Mybatis Plus | Fluent Mybatis |
---|---|---|
代码生成 | 生成 Entity | 生成Entity, 再通过编译生成 Mapper, Query, Update 和 SqlProvider |
Generator易用性 | 低 | 高 |
和Mybatis的共生关系 | 需替换原有的SqlSessionFactoryBean | 对Mybatis没有任何修改,原来怎么用还是怎么用 |
动态SQL构造方式 | 应用启动时, 根据Entity注解信息构造动态xml片段,注入到Mybatis解析器 | 应用编译时,根据Entity注解,编译生成对应方法的SqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解关联 |
动态SQL结果是否容易DEBUG跟踪 | 不容易debug | 容易,直接定位到SQLProvider方法上,设置断点即可 |
动态SQL构造 | 通过硬编码字段名称, 或者利用Entity的get方法的lambda表达式 | 通过编译手段生成对应的方法名,直接调用方法即可 |
字段变更后的错误发现 | 通过get方法的lambda表达的可以编译发现,通过字段编码的无法编译发现 | 编译时便可发现 |
不同字段动态SQL构造方法 | 通过接口参数方式 | 通过接口名称方式, FluentAPI的编码效率更高 |
语法渲染特点 | 无 | 通过关键变量select, update, set, and, or可以利用IDE语法渲染, 可读性更高 |
Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比
本文主要介绍了Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比,分享给大家,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
目录
三者实现对比
使用fluent mybatis 来实现上面的功能
换成mybatis原生实现效果
换成mybatis plus实现效果
生成代码编码比较
fluent mybatis生成代码设置
mybatis plus代码生成设置
FluentMybatis特性一览
三者对比总结
Fluent Mybatis介绍和源码
使用fluent mybatis可以不用写具体的xml文件,通过java api可以构造出比较复杂的业务sql语句,做到代码逻辑和sql逻辑的合一。
不用再需要在Dao中组装查询或更新操作,在xml或mapper中再组装次参数。
那对比原生Mybatis, Mybatis Plus或者其他框架,FluentMybatis提供了哪些便利呢?
我们通过一个比较典型的业务需求来具体实现和对比下,假如有学生成绩表结构如下:
create table `student_score` ( id bigint auto_increment comment '主键ID' primary key, student_id bigint not null comment '学号', gender_man tinyint default 0 not null comment '性别, 0:女; 1:男', school_term int null comment '学期', subject varchar(30) null comment '学科', score int null comment '成绩', gmt_create datetime not null comment '记录创建时间', gmt_modified datetime not null comment '记录最后修改时间', is_deleted tinyint default 0 not null comment '逻辑删除标识' ) engine = InnoDB default charset=utf8;
现在有需求:
统计2000年三门学科(‘英语', ‘数学', ‘语文')及格分数按学期,学科统计最低分,最高分和平均分,
且样本数需要大于1条,统计结果按学期和学科排序
我们可以写sql语句如下
select school_term, subject, count(score) as count, min(score) as min_score, max(score) as max_score, avg(score) as max_score from student_score where school_term >= 2000 and subject in ('英语', '数学', '语文') and score >= 60 and is_deleted = 0 group by school_term, subject having count(score) > 1 order by school_term, subject;
那上面的需求,分别用fluent mybatis, 原生mybatis 和 Mybatis plus来实现一番。
三者实现对比
使用fluent mybatis 来实现上面的功能
具体代码
我们可以看到fluent api的能力,以及IDE对代码的渲染效果。
换成mybatis原生实现效果
定义Mapper接口
public interface MyStudentscoreMapper { List> summaryscore(SummaryQuery paras); }
定义接口需要用到的参数实体 SummaryQuery
@Data @Accessors(chain = true) public class SummaryQuery { private Integer schoolTerm; private List subjects; private Integer score; private Integer minCount; }
定义实现业务逻辑的mapper xml文件
select school_term, subject, count(score) as count, min(score) as min_score, max(score) as max_score, avg(score) as max_score from student_score where school_term >= #{schoolTerm} and subject in #{item} and score >= #{score} and is_deleted = 0 group by school_term, subject having count(score) > #{minCount} order by school_term, subject
实现业务接口(这里是测试类, 实际应用中应该对应Dao类)
@RunWith(springrunner.class) @SpringBoottest(classes = QuickStartApplication.class) public class MybatisDemo { @Autowired private MyStudentscoreMapper mapper; @Test public void mybatis_demo() { // 构造查询参数 SummaryQuery paras = new SummaryQuery() .setSchoolTerm(2000) .setSubjects(Arrays.asList("英语", "数学", "语文")) .setscore(60) .setMinCount(1); List> summary = mapper.summaryscore(paras); System.out.println(summary); } }
总之,直接使用mybatis,实现步骤还是相当的繁琐,效率太低。
那换成mybatis plus的效果怎样呢?
换成mybatis plus实现效果
mybatis plus的实现比mybatis会简单比较多,实现效果如下
但正如红框圈出的,写mybatis plus实现用到了比较多字符串的硬编码(可以用Entity的get lambda方法部分代替字符串编码)。字符串的硬编码,会给开发同学造成不小的使用门槛,个人觉的主要有2点:
字段名称的记忆和敲码困难
Entity属性跟随数据库字段发生变更后的运行时错误
其他框架,比如TkMybatis在封装和易用性上比mybatis plus要弱,就不再比较了。
生成代码编码比较
fluent mybatis生成代码设置
public class AppEntityGenerator { static final String url = "jdbc:MysqL://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8"; public static void main(String[] args) { FileGenerator.build(Abc.class); } @Tables( /** 数据库连接信息 **/ url = url, username = "root", password = "password", /** Entity类parent package路径 **/ basePack = "cn.org.fluent.mybatis.springboot.demo", /** Entity代码源目录 **/ srcDir = "spring-boot-demo/src/main/java", /** Dao代码源目录 **/ daoDir = "spring-boot-demo/src/main/java", /** 如果表定义记录创建,记录修改,逻辑删除字段 **/ gmtCreated = "gmt_create", gmtModified = "gmt_modified", logicDeleted = "is_deleted", /** 需要生成文件的表 ( 表名称:对应的Entity名称 ) **/ tables = @Table(value = {"student_score"}) ) static class Abc { } }mybatis plus代码生成设置
public class CodeGenerator { static String dbUrl = "jdbc:MysqL://localhost:3306/fluent_mybatis_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8"; @Test public void generateCode() { GlobalConfig config = new GlobalConfig(); DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDbType(DbType.MysqL) .setUrl(dbUrl) .setUsername("root") .setPassword("password") .setDriverName(Driver.class.getName()); StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig .setCapitalMode(true) .setEntityLombokModel(false) .setNaming(NamingStrategy.underline_to_camel) .setColumnNaming(NamingStrategy.underline_to_camel) .setEntityTableFieldAnnotationEnable(true) .setFieldPrefix(new String[]{"test_"}) .setInclude(new String[]{"student_score"}) .setLogicDeleteFieldName("is_deleted") .setTableFillList(Arrays.asList( new TableFill("gmt_create", FieldFill.INSERT), new TableFill("gmt_modified", FieldFill.INSERT_UPDATE))); config .setActiveRecord(false) .setIdType(IdType.AUTO) .setoutputDir(System.getProperty("user.dir") + "/src/main/java/") .setFileOverride(true); new AutoGenerator().setGlobalConfig(config) .setDataSource(dataSourceConfig) .setStrategy(strategyConfig) .setPackageInfo( new PackageConfig() .setParent("com.mp.demo") .setController("controller") .setEntity("entity") ).execute(); } }
FluentMybatis特性一览
三者对比总结
看完3个框架对同一个功能点的实现, 各位看官肯定会有自己的判断,笔者这里也总结了一份比较。
-
Mybatis Plus
Fluent Mybatis
代码生成
生成 Entity, Mapper, Wrapper等文件, 并且Generator很好用
只生成Entity, 再通过编译生成 Mapper, Query, Update 和 sqlProvider
和Mybatis的共生关系
需要替换原有的sqlSessionfactorybean
对Mybatis没有任何修改,原来怎么用还是怎么用
动态sql构造方式
应用启动时, 根据Entity注解信息构造动态xml片段,注入到Mybatis解析器
应用编译时,根据Entity注解,编译生成对应方法的sqlProvider,利用mybatis的Mapper上@InsertProvider @SelectProvider @UpdateProvider注解关联
动态sql结果是否容易DEBUG跟踪
不容易debug
容易,直接定位到sqlProvider方法上,设置断点即可
动态sql构造
通过硬编码字段名称, 或者利用Entity的get方法的lambda表达式
通过编译手段生成对应的方法名,直接调用方法即可
字段变更后的错误发现
通过get方法的lambda表达的可以编译发现,通过字段编码的无法编译发现
编译时便可发现
不同字段动态sql构造方法
通过接口参数方式
通过接口名称方式, FluentAPI的编码效率更高
语法渲染特点
无
通过关键变量select, update, set, and, or可以利用IDE语法渲染, 可读性更高
Fluent Mybatis介绍和源码
Fluent Mybatis文档&示例
Fluent Mybatis源码, github
到此这篇关于Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比的文章就介绍到这了,更多相关Fluent Mybatis,原生Mybatis,Mybatis Plus内容请搜索小编以前的文章或继续浏览下面的相关文章希望大家以后多多支持小编!
idea springboot2 集成Mybatis使用mybatis-generator-plugin生成代码
参考博客:
详细使用步骤:https://blog.csdn.net/u010358168/article/details/86246351
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>mybatis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>5.1.46</scope>
</dependency>
<!--需要手动添加的依赖-->
<!--使用durid连接池的依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- mybatis generator 自动生成代码插件 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<!-- 配置数据库链接及mybatis generator core依赖 生成mapper时使用 -->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<!-- 配置生成器 -->
<generatorConfiguration>
<context id="DB2Tables" targetRuntime="MyBatis3Simple">
<commentGenerator>
<property name="suppressDate" value="true"/>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<!-- 数据库链接URL,用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mvctest?serverTimezone=GMT%2B8"
userId="hu"
password="123456">
</jdbcConnection>
<!-- 类型转换 -->
<javaTypeResolver>
<!-- 是否使用BigDecimals,false可自动转化以下类型(Long Integer Short等) -->
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<!-- 生成模型的包名和位置-->
<javaModelGenerator targetPackage="com.example.mybatis.pojo" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
<!--<property name="trimStrings" value="true"/>-->
</javaModelGenerator>
<!-- 生成映射文件的包名和位置-->
<sqlMapGenerator targetPackage="mappers" targetProject="src/main/resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<!-- 生成DAO的包名和位置 -->
<javaClientGenerator type="XMLMAPPER" targetPackage="com.example.mybatis.mapper" targetProject="src/main/java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名-->
<table tableName="user" domainObjectName="User" >
<property name="useActualColumnNames" value="false"/>
<!-- 数据库表主键 -->
<generatedKey column="id" sqlStatement="Mysql" identity="true"/>
</table>
</context>
</generatorConfiguration>
注意问题:
如果不成功:
主要是数据库连接的版本的问题,我这里是5.1.34对应的是mysql5.7.20
java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】
一、概述
三款框架的功能对比
|
Mybatis-generator |
通用Mapper |
Mybatis-Plus |
代码生成器 |
支持自动生成Model,Mapper,Mapper XML文件 生成方式不够灵活; 生成代码功能较为简单 |
支持自动生成Entity,Mapper,Mapper XML文件; 提供通用的Mapper模板,生成方式较灵活; 生成的Model文件包含注释能够很好地与数据库表完成映射 |
支持自动生成Entity,Mapper,Mapper XML,Service,Controller文件; 提供BaseMapper接口 |
CRUD操作 |
代码生成后每个Mapper有固定的CRUD方法; 在每个Mapper上分别扩展 |
提供通用Mapper接口;方便构造统一service 可以扩展通用接口 |
提供BaseMapper接口; 可以扩展通用接口 |
条件构造器 |
每个实体类自己的Example构造条件【对象方式】 |
提供通用Example【构建sql】 |
提供Wrapper进行复杂条件构造 |
乐观锁 |
|
支持 |
支持 |
主键策略 |
|
支持 |
支持 |
分页 |
|
|
支持 |
逻辑删除 |
|
|
支持 |
通用枚举 |
|
|
支持 |
攻击Sql阻断 |
|
|
支持 |
性能分析 |
|
|
支持 |
通用Mapper是对Mybatis-generator的升级改造,解决了使用Mybatis-generator可能需要大量重构的问题,并且在这个基础上加入了一些新的功能。
Mybatis-Plus可以看作是在另一个方向上对Mybatis的升级改造,不仅能够根据数据库表快速生成pojo实体类,还封装了大量CRUD方法,使用Wrapper解决了复杂条件构造等问题,更是根据开发中常见的问题给出了一系列解决方案。
在拥有Maven和Spring boot的开发框架下,MBG、通用Mapper和MP都可以快速地完成安装,相比于MBG和通用Mapper仅需要执行插件就可以完成基本的开发工作,MP可能需要更多的开发工作量。
最佳实践参看代码:https://github.com/bjlhx15/java_base_architecture.git
二、Mybatis-generator
MyBatis Generator(MBG)是MyBatis MyBatis 和iBATIS的代码生成器。它为所有版本的MyBatis以及版本2.2.0之后的iBATIS版本生成代码。它将根据数据库表生成可用于访问表的文件。
Mybatis-generator主要完成的工作是依据数据库表创建对应的model、dao、mapping文件,可以通过Maven插件或者mybatis-generator的jar包生成。
这里介绍Maven插件使用方法:
1、在pom.xml文件中加入mybatis-generator系列插件;
2、创建generatorConfig.xml文件,在配置文件中指定数据库连接地址、生成类的存放地址、生成对应表的类名等信息;
3、执行mybatis-generator插件,即可生成相应文件;
4、此外,mybatis-generator自动生成了example类用于构造复杂的筛选条件
Mybatis-generator使用较为简单,生成的DAO类及映射文件中包含基本的CRUD操作。
需要注意的是,在一次项目中多次执行mybatis-generator,xml文件会追加,会覆盖原本的Model、DAO;可以使用如下方式
1、每次清理要生成的xml
2、自动生成的写入auto,
3、个人扩展的使用上图方式
可以参看上述github代码
三、通用Mapper【tk.mybatis】
官网:https://github.com/abel533/Mapper/wiki
当数据库字段变化频繁时,使用MBG(mybatis-generator)会带来大量的重构工作,对此,通用Mapper给出的解决办法是:给予开发者一个具备丰富的单表方法并且容易扩展的通用的Mapper。
通用Mapper是对单表的CRUD操作进行了较为详细的实现,使得开发人员可以随意的按照自己的需求选择通用的方法,同时允许开发人员便捷地对通用Mapper进行扩展。
1. 在pom.xml中添加插件配置


<!-- 命令:mvn mybatis-generator:generate -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.6</version>
<configuration>
<!-- 配置实际调用地址-->
<configurationFile>src/main/resources/mybatis_generatorConfig/generatorConfig-base.xml
</configurationFile>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.0</version>
</dependency>
</dependencies>
</plugin>
可以看到,通用Mapper的代码生成实际上是使用了MGB,因此通用Mapper的代码生成器只是调用了MGB,然后在这个基础上加入了一些元素来方便开发。
2. 配置文件generatorConfig.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE generatorConfiguration PUBLIC
"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd" >
<generatorConfiguration>
<!--导入属性配置,前面我们写的一个配置文件,你也可以直接使用mybatis的jdbc的配置文件 -->
<properties resource="jdbc.properties"></properties>
<!-- 数据库驱动,注意,这里必须要修改成你的数据库的驱动地址 -->
<!-- 如果 pom配置这里可以不写-->
<!-- <classPathEntry location=".m2/repository/mysql/mysql-connector-java/5.1.8/mysql-connector-java-5.1.8.jar"/>-->
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<plugin type="tk.mybatis.mapper.generator.MapperPlugin">
<property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
<property name="caseSensitive" value="true"/>
</plugin>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="${jdbc.driver}"
connectionURL="${jdbc.url}"
userId="${jdbc.username}" password="${jdbc.password}">
</jdbcConnection>
<!-- <javaTypeResolver>-->
<!-- <property name="forceBigDecimals" value="false"/>-->
<!-- </javaTypeResolver>-->
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.github.bjlhx15.mybatis.springboot.base.model.auto"
targetProject="../tk-mybatis-springboot-base1/src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true"/>
</javaModelGenerator>
<!-- targetProject:mapper xml 映射文件生成的位置 -->
<sqlMapGenerator targetPackage="autoxml"
targetProject="../tk-mybatis-springboot-base1/src/main/resources/mapper/">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</sqlMapGenerator>
<!--targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.github.bjlhx15.mybatis.springboot.base.repository.auto"
targetProject="../tk-mybatis-springboot-base1/src/main/java">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false"/>
</javaClientGenerator>
<!-- 指定数据库表 -->
<table tableName="accountbalance" domainObjectName="AccountBalance">
<generatedKey column="id" sqlStatement="JDBC"/>
</table>
</context>
</generatorConfiguration>
与MGB原有的配置文件相比,这里只是多了一个插件的配置,这个插件的作用是:配置生成的Mapper接口都会自动继承这个接口,也就是说,使用通用Mapper生成的mapper接口即使看上去空空如也,但已经具备了大量的对数据库的操作方法。此外,通用 Mapper 专用代码生成器生成的 Model 会在原有基础上增加 @Table,@Id,@Column 等注解,方便自动与数据库字段进行映射。
3. 在 pom.xml 这一级目录的命令行窗口执行 mvn mybatis-generator:generate或者直接在执行mvn插件即可。
4. 通用Mapper同样有Example的设计,与MGB不同的是,MDB会对每一个表生成对应的Example类,而通用Mapper提供了一个统一的Example类,这个类和 MBG 生成的相比,需要自己设置属性名,这个类还额外提供了更多的方法。
通用Mapper可以看作是MGB的改进和扩展,一定程度上解决了使用MGB重构的问题。
可以参看上述github代码
四、Mybatis-Plus
官网地址:https://mp.baomidou.com/guide/generator.html
(以下简称MP)是Mybatis的增强工具(MBG和通用Mapper可看成插件),在Mybatis的基础上增加了很多功能,简化开发,提高效率。
在Spring Boot中的引入:
1. 在maven中添加MP启动器
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.1.2</version>
</dependency>
2. 要使用代码生成器还需要添加模板引擎依赖
参看地址:AutoGenerator的使用参考 https://mybatis.plus/guide/generator.html 。
添加 模板引擎 依赖,MyBatis-Plus 支持 Velocity(默认)、Freemarker、Beetl,用户可以选择自己熟悉的模板引擎,如果都不满足您的要求,可以采用自定义模板引擎。
Velocity(默认):
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.1</version>
</dependency>
Freemarker:
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.29</version>
</dependency>
Beetl:
<dependency>
<groupId>com.ibeetl</groupId>
<artifactId>beetl</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
注意!如果您选择了非默认引擎,需要在 AutoGenerator 中 设置模板引擎。


AutoGenerator generator = new AutoGenerator();
// set freemarker engine
generator.setTemplateEngine(new FreemarkerTemplateEngine());
// set beetl engine
generator.setTemplateEngine(new BeetlTemplateEngine());
// set custom engine (reference class is your custom engine class)
generator.setTemplateEngine(new CustomTemplateEngine());
// other config
...
3、代码的自动生成。AutoGenerator是MP的代码生成器,通过调用AutoGenerator,进行相应的模板、策略配置可以快速生成Entity、Mapper、Mapper XML、Service、Controller各个模块的代码。
4. MP将通用的CRUD操作封装进BaseMapper接口,而自动生成的Mapper接口便自动继承了BaseMapper接口。复杂的Sql操作,则可以使用QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper)进行动态Sql拼接。
5、此外,MP还支持分页、逻辑删除、通用枚举、Sql注入等功能,在:https://mp.baomidou.com/guide/generator.html
还有性能分析插件:https://mp.baomidou.com/guide/performance-analysis-plugin.html
与MBG不同,使用Mybatis-Plus自动生成代码需要编写代码,通过调用AutoAutoGenerator类实现代码生成,从这方面来说不如使用插件方便。但是它丰富的功能以及只是相对复杂的配置还是使它领先于MBG以及通用Mapper。
双方都
关于MyBatis-Plus使用和mybatis plus 用法的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Fluent Mybatis, 原生Mybatis, Mybatis Plus三者功能对比、Fluent Mybatis,原生Mybatis,Mybatis Plus三者功能对比、idea springboot2 集成Mybatis使用mybatis-generator-plugin生成代码、java-mybaits-015-mybatis逆向工程最佳实践【基础mybatis-generator、tk.mybatis、mubatis-plus】的相关知识,请在本站寻找。
本文标签: