目录
MyBatisPlus简介:
代码编写
BaseMapper源码解析
Sevice CRUD接口
常用注解
@TableLogic
雪花算法
条件构造器wapper
插件
1.分页插件
2.利用插件自定义分页条件
乐观锁插件
通用枚举
代码生成器
多数据源
MyBayisX插件
特性:
框架结构:
1.实体类User
安装lombok插件后,实体类User的除有参构造外的无参构造和get/set方法都可以由Data注解完成
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
2.mapper层的UserMapper接口
直接继承由mybatisplus提供的BaseMapper(该类为我们提供了一系列增删查改的方法)
public interface UserMaper extends BaseMapper {
}
3.在applicationContext.xml中配置,扫描mapper接口所在包及数据库连接配置等。
各种增删查改方法及具体实现
●通用Service CRUD封装IService接口,进一步封装CRUD采用get 查询单行,remove删除list 查询集合,page分页前缀命名方式区分Mapper 层避免混淆,
●泛型τ为任意实体对象
●建议如果存在自定义通用Service方法的可能,请创建自己的IBaseService 继承Mybatis-Plus 提供的基类
●对象Wrapper 为条件构造器
创建UserService接口继承MyBtis-Plus提供的IService
public interface UserService extends IService {
}
创建UserServiceImpl实现类,继承MyBtis-Plus提供的ServiceImpl实现类,实现UserService接口
@Service
public class UserServiceImpl extends ServiceImpl implements UserService {
}
@TableName
在实体类上添加@tableName注解,标识实体类对应的表。因为MyBatis-Plus在确定操作的表时,由BaseMapper的泛型决定,即实体类型决定,且默认操作的表名和实体类型的类名一致,如果不一致就会发生错误,这时就需要用@tableName注解指定该实体类对应的表了。
当实体类所对应的表都有固定的前缀,例如t_或tbl_ 此时,可以使用MyBatis-Plus提供的全局配置,为实体类所对应的表名设置默认的前缀,那么就 不需要在每个实体类上通过@TableName标识实体类对应的表
@TableId
将属性所对应的字段指定为主键。
MyBatis-Plus在实现CRUD时,会默认将id作为主键列,并在插入数据时,默认 基于雪花算法的策略生成id。若实体类和表中表示主键的不是id,而是其他字段,例如uid,MyBatis-Plus不会自动识别uid为主键列。这时可以在主键字段上用@TableId将其标识为主键。
@TableId注解的value属性:用于指定主键的字段(当实体类中表示主键的字段为id时(符合MyBatis-Plus在实现CRUD时,会默认将id作为主键列的规则),但数据库中的主键为uid或其他,可以通过@TableId注解的value属性指定主键字段名为数据库中的主键字段名)
@TableId注解的type属性:设置主键的生成策略(MyBatis-Plus默认的主键生成策略是根据雪花算法生成主键,可以利用type属性设置生成策略为自增)
配置全局主键生成策略
@TableFiled
指定普通属性所对应的数据库表的字段名。
若实体类中的属性和表中的字段不一致, 例如实体类属性name,表中字段username 此时需要在实体类属性上使用@TableField("username")设置属性所对应的字段名。
若实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格 例如实体类属性userName,表中字段user_name 此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格
逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据库 中仍旧能看到此条数据记录。使用场景:可以进行数据恢复
步骤1:在数据库中创建逻辑删除状态列,设置默认值为0
步骤2:实体类中添加逻辑删除属性
步骤3:测试
结果是被逻辑删除的数据的默认值会变为1且不会被查询到
雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的 主键的有序性。
整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。
1.QueryWrapper
功能:组装查询条件、组装排序条件、修改功能、组装删除条件、条件优先级、组装select语句、实现子查询等等。
组装查询条件:
@Test
public void test01(){
//查询姓名含b,年龄10-20,邮箱不为空的用户
QueryWrapper q1=new QueryWrapper<>();
q1.like("name","b").between("age",10,20).isNotNull("email");
List userList = userMapper.selectList(q1);
userList.forEach(System.out::println);
}
修改功能:
@Test
public void test02(){
QueryWrapper q2=new QueryWrapper<>();
//将(年龄小于20并且用户名中包含有b)或邮箱不为null的用户信息修改为...
q2.lt("age",20).like("name","b").or().isNotNull("email");
User user=new User("小明",17,"[email protected]");
userMapper.update(user,q2);
}
组装select语句:
@Test
public void test03(){
//查询用户的用户名,年龄,邮箱信息--组装select
QueryWrapper q3=new QueryWrapper<>();
q3.select("name","age","email");
List
实现子查询:
@Test
public void test04(){
//查询id小于等于3的用户信息(SELECT id,name,age,email FROM user WHERE (id IN (select id from user where id<=3)))
QueryWrapper q4=new QueryWrapper<>();
q4.inSql("id","select id from user where id<=3");
List users = userMapper.selectList(q4);
users.forEach(System.out::println);
}
2.UpdateWrapper
功能:修改
@Test
public void test05(){
//将用户名中包含有黑并且(年龄大于20或邮箱为null)的用户信息修改
UpdateWrapper u1=new UpdateWrapper<>();
u1.like("name","黑").and(i->i.gt("age",20).or().isNotNull("email"));
u1.set("name","鲲").set("age",13);
userMapper.update(null,u1);
}
3.condition
背景:在真正开发的过程中,组装条件是常见的功能,而这些条件数据来源于用户输入,是可选的,因 此我们在组装这些条件时,必须先判断用户是否选择了这些条件,若选择则需要组装该条件,若 没有选择则一定不能组装,以免影响SQL执行的结果
加StringUtils工具类的使用,加使用带condition参数的重载方法构建查 询条件
@Test
public void test06() {
//定义查询条件,有可能为null(用户未输入或未选择)
String username = null;
Integer ageBegin = 10;
Integer ageEnd = 24;
QueryWrapper queryWrapper = new QueryWrapper<>();
//StringUtils.isNotBlank()判断某字符串是否不为空且长度不为0且不由空白符(whitespace)构成
queryWrapper.like(StringUtils.isNotBlank(username), "username", "a")
.ge(ageBegin != null, "age", ageBegin)
.le(ageEnd != null, "age", ageEnd);
userMapper.selectList(queryWrapper);
}
4.LambdaQueryWrapper
防止构造条件指定字段名时写错,用法与QueryWrapper相似,但要在构造条件时用Lambda表达式的方式获取字段
@Test
public void test06() {
//定义查询条件,有可能为null(用户未输入)
String username = "a";
Integer ageBegin = 10;
Integer ageEnd = 24;
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();
//避免使用字符串表示字段,防止运行时错误
queryWrapper
.like(StringUtils.isNotBlank(username), User::getName, username)
.ge(ageBegin != null, User::getAge, ageBegin)
.le(ageEnd != null, User::getAge, ageEnd);
userMapper.selectList(queryWrapper);
}
5.LambdaUpdateWrapper
防止构造条件指定字段名时写错,用法与UpdateWrapper相似,但要在构造条件时用Lambda表达式的方式获取字段
@Test
public void test7() {
//组装set子句
LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper
.set(User::getAge, 18)
.set(User::getEmail, "[email protected]")
.like(User::getName, "a")
.and(i -> i.lt(User::getAge, 24).or().isNull(User::getEmail)); //lambda表达式内的逻辑优先运算
User user = new User();
userMapper.update(user, updateWrapper);
}
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能,在applicationContext.xml中配置
(1)UserMapper中添加方法
// @param page mybatisPlus提供的分页对象, 即自动分页,必须放在第一位
Page selectAgeWithPages(@Param("page") Page page,@Param("age") Integer age);
(2)UserMapper.xml中写sql语句
(3)测试
@Test
public void testPageVo(){
Page page=new Page<>(1,3);
userMapper.selectAgeWithPages(page,20);
System.out.println(page);
System.out.println("当前页:"+page.getCurrent());
System.out.println("每页显示的条数:"+page.getSize());
System.out.println("总记录数:"+page.getTotal());
System.out.println("总页数:"+page.getPages());
System.out.println("是否有上一页:"+page.hasPrevious());
System.out.println("是否有下一页:"+page.hasNext());
}
场景
乐观锁实现流程
1.在数据库中添加version字段,取出记录时,获取当前version.
2.@Version注解:用来标识表示乐观锁版本号的字段
3.添加乐观锁插件配置
数据库中的表中的有些字段值是固定的,例如性别(男或女),此时我们可以使用MyBatis-Plus的通用枚举来实现
1.创建通用枚举类型
@EnumValue注解:将注解所标识的属性的值存储到数据库中
@Getter
public enum SexEnum {
MALE(1, "男"),
FEMALE(2, "女");
@EnumValue
private Integer sex;
private String sexName;
SexEnum(Integer sex, String sexName) {
this.sex = sex;
this.sexName = sexName;
}
}
2.在applicationContext.xml中配置扫描通用枚举类型
1.引入依赖
com.baomidou
mybatis-plus-generator
3.5.1
org.freemarker
freemarker
2.3.31
2.快速生成
public class FastAutoGeneratorTest {
public static void main(String[] args) {
FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus",
"root", "123456")
.globalConfig(builder -> {
builder.author("zc") // 设置作者
//.enableSwagger() // 开启 swagger 模式
.fileOverride() // 覆盖已生成文件
.outputDir("D://mybatis_plus"); // 指定输出目录
})
.packageConfig(builder -> {
builder.parent("com.zc") // 设置父包名
.moduleName("mybatisplus") // 设置父包模块名
.pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus"));
// 设置mapperXml生成路径
})
.strategyConfig(builder -> {
builder.addInclude("t_user") // 设置需要生成的表名
.addTablePrefix("t_", "c_"); // 设置过滤表前缀
})
.templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker
引擎模板,默认的是Velocity引擎模板
.execute();
}
}
适用于多种场景:纯粹多库、读写分离、- 主多从、混合模式等
MyBatis-Plus为我们提供了强大的mapper和service模板,能够大大的提高开发效率 但是在真正开发过程中,MyBatis-Plus并不能为我们解决所有问题,例如一些复杂的SQL,多表 联查,我们就需要自己去编写代码和SQL语句,我们该如何快速的解决这个问题呢,这个时候可以使用MyBatisX插件 MyBatisX一款基于 IDEA 的快速开发插件,为效率而生。
附MybatisPlus官方网站: 简介 | MyBatis-PlusMyBatis-Plus 官方文档https://baomidou.com/pages/24112f/