MyBatis-Plus笔记(入门)
官方文档
https://mybatis.plus/guide/
本篇基于springboot
,mybatis Plus
的版本为3.4.2
本篇对应的github地址
https://github.com/monkeyKinn/StudyMyBatisPlus
觉得有用给个Star哦~
Star
Star
Star
建库建表
#创建用户表CREATE TABLE user (id BIGINT(20) PRIMARY KEY NOT NULL COMMENT '主键',name VARCHAR(30) DEFAULT NULL COMMENT '姓名',age INT(11) DEFAULT NULL COMMENT '年龄',email VARCHAR(50) DEFAULT NULL COMMENT '邮箱',manager_id BIGINT(20) DEFAULT NULL COMMENT '直属上级id',create_time DATETIME DEFAULT NULL COMMENT '创建时间',CONSTRAINT manager_fk FOREIGN KEY (manager_id)REFERENCES user (id)) ENGINE=INNODB CHARSET=UTF8;#初始化数据:INSERT INTO user (id, name, age, email, manager_id, create_time)VALUES (1087982257332887553, '大boss', 40, 'boss@baomidou.com', NULL, '2019-01-11 14:20:20'),(1088248166370832385, '王天风', 25, 'wtf@baomidou.com', 1087982257332887553, '2019-02-05 11:12:22'),(1088250446457389058, '李艺伟', 28, 'lyw@baomidou.com', 1088248166370832385, '2019-02-14 08:31:16'),(1094590409767661570, '张雨琪', 31, 'zjq@baomidou.com', 1088248166370832385, '2019-01-14 09:15:15'),(1094592041087729666, '刘红雨', 32, 'lhm@baomidou.com', 1088248166370832385, '2019-01-14 09:48:16');
引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></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><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13</version><scope>test</scope></dependency>
配置文件
spring.application.name=MyBatisPlusspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/mp?useSSL=false&serverTimezone=GMT%2B8spring.datasource.username=rootspring.datasource.password=admin
创建实体类
@Datapublic class User{/** 主键 */private Long id;/** 姓名 */private String name;/** 年龄 */private Integer age;/** 邮件 */private String email;/** 直属上级id */private Long managerId;/** 创建时间 */private LocalDateTime createTime;}
创建mapper接口
public interface UserMapper extends BaseMapper<User> {}
启动类上加上注解
@SpringBootApplication// 注意这里的包扫描路径 要写到mapper所在的包名上@MapperScan("com.jsc.mybatisplus.mapper")public class MyBatisPlusApplication {public static void main(String[] args) {SpringApplication.run(MyBatisPlusApplication.class, args);}}
创建测试类
@SpringBootTest@RunWith(SpringRunner.class)class MyBatisPlusApplicationTests {// 后面会用到,此为创建条件构造器private QueryWrapper<User> query = Wrappers.query();@Autowiredprivate UserMapper userMapper;@Testvoid selectAllTest() {List<User> users = userMapper.selectList(null);Assertions.assertEquals(5,users.size());users.forEach(System.out::println);}}
以上 ,入门练手
通用mapper新增方法
配置文件加上日志输出
spring.application.name=MyBatisPlusspring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/mp?useSSL=false&serverTimezone=GMT%2B8spring.datasource.username=rootspring.datasource.password=admin#日志输出配置logging.level.root=warn#只想看这个包里的sql日志 trace是最低级别logging.level.com.jsc.mybatisplus.mapper=trace
创建测试类
@Testvoid insertTest() {User user = new User();user.setName("老金");user.setAge(18);// 没有email 默认不给插入 没有id 是因为默认雪花iduser.setManagerId(1087982257332887553L);user.setCreateTime(LocalDateTime.now());int rows = userMapper.insert(user);System.out.println("影响行数: " + rows);}
常用注解
@TableName("表名") //在实体类上,用来当db中表和实体类名不一致时候,指定表@TableId //在字段上,用来指定对应的主键,当数据库中的主键不是id命名时,实体类也不是id时用@TableField("字段名") //在实体类上,用来指定对应的字段名
排除非表字段的三种方式
1.
transient //关键字 无法被序列化(存到磁盘)
2.
static //关键字 只有一份 属于类
3.
@TableField(exit=false) //默认是true,数据库中存在
查询
基本查询
@Testvoid selectByIdTest() {// 根据id查询User user = userMapper.selectById(1382699085670719489L);// User(id=1382699085670719489, name=老金, age=18, email=null, managerId=1087982257332887553, createTime=2021-04-15T22:15:26)System.out.println(user);}@Testvoid selectBatchIdsTest() {// 根据id批量查询List<Long> ids = Arrays.asList(1382699085670719489L, 1094592041087729666L, 1094590409767661570L);List<User> users = userMapper.selectBatchIds(ids);users.forEach(System.out::println);}@Testvoid selectByMapTest() {Map<String, Object> map = new HashMap<>();// map.put("name", "老金");// map的key是数据库中的字段map.put("age", 27);// WHERE name = ? AND age = ?// WHERE age = ?List<User> users = userMapper.selectByMap(map);System.out.println(users);}
以条件构造器为参数
@Testvoid selectByWrapper0() {/** 1、名字中包含雨并且年龄小于40* name like '%雨%' and age<40* 条件构造器*/query.like("name", "雨").lt("age", 40);List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper1() {/** 名字中包含雨年并且龄大于等于20且小于等于40并且email不为空* name like '%雨%' and age between 20 and 40 and email is not null*/query.like("name", "雨").between("age", 20, 40).isNotNull("email");List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper2() {/** 名字为王姓或者年龄大于等于25,按照年龄降序排列,年龄相同按照id升序排列* name like '王%' or age>=25 order by age desc,id asc*/query.like("name", "王").or().ge("age", 18).orderByDesc("age").orderByAsc("id");List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper3() {/** 创建日期为2019年2月14日并且直属上级为名字为王姓 --函数开头用apple拼接sql* date_format(create_time,'%Y-%m-%d')='2019-02-14' and manager_id in (select id from user where name like '王%')*/query.apply("date_format(create_time,'%Y-%m-%d')={0}", "2019-02-14").inSql("manager_id", "select id from user where name like '王%'");List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper4() {/** 名字为王姓并且(年龄小于40或邮箱不为空)* name like '王%' and (age<40 or email is not null)*/query.likeRight("name","王").and(qw->qw.lt("age",40 ).or().isNotNull("email"));List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper5() {/** 名字为王姓或者(年龄小于40并且年龄大于20并且邮箱不为空)* name like '王%' or (age<40 and age>20 and email is not null)*/query.likeRight("name","王").or(qw->qw.lt("age",40 ).gt("age",20).isNotNull("email"));List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper6() {/** (年龄小于40或邮箱不为空)并且名字为王姓,nested 正常嵌套 不带 AND 或者 OR* (age<40 or email is not null) and name like '王%'*/query.nested(qw->qw.lt("age",40).or().isNotNull("email")).likeRight("name","王");List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper7() {/** 年龄为30、31、34、35* age in (30、31、34、35)*/query.in("age",18,30,31,34,35);List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}
select中字段不全部出现的查询
@Testvoid selectByWrapper8() {/** 10、名字中包含雨并且年龄小于40(需求1加强版)第一种情况: select id,name -- 就用select("")from userwhere name like '%雨%' and age<40第二种情况: select id,name,age,emailfrom userwhere name like '%雨%' and age<40*/query.like("name","雨").lt("age",40).select("name","age");List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}@Testvoid selectByWrapper9() {/** 10、名字中包含雨并且年龄小于40(需求1加强版)第一种情况: select id,name -- 就用select("")from userwhere name like '%雨%' and age<40第二种情况: select id,name,age,email -- 就用select("")from userwhere name like '%雨%' and age<40*/query.like("name","雨").lt("age",40).select(User.class,info ->!info.getColumn().equals("create_time")&&!info.getColumn().equals("manager_id"));List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}
条件构造器中condition的作用(执行条件.可理解为条件查询)
@Testvoid selectByCondition() {// 根据参数条件查询// String name = "金";String name = "玉";String age = "18";// 如果不为空,就有后面的条件加入到sql中query.like(StringUtils.isNotBlank(name),"name",name).eq(StringUtils.isNotBlank(age),"age",age);List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}
创建条件构造器时,传入实体对象
@Testvoid selectByWrapperEntity() {/** 使用场景:* 1、通过实体传过来数据* 2.不想永理科这样的构造器,默认是等值的* 如果不想等值,在实体类中加上注解* @TableField(condition=SqlCondition.like)* 小于的话就是="%s<#{%s}"* 列名<列值*/User whereUser = new User();whereUser.setName("老金");whereUser.setAge(18);query = Wrappers.query(whereUser);// query.like("name", "雨").lt("age", 40);List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}
条件构造器中allEq用法
@Testvoid selectByWrapperAllEq() {HashMap<String, Object> params = new HashMap<>();params.put("name", "王天风");params.put("age", null);// 后面的false,是忽略null值的列// query.allEq(params,false);// 前面一个函数是过滤用的 比如这里就是不包含age列query.allEq((k,v)->!"age".equals(k),params);List<User> users = userMapper.selectList(query);users.forEach(System.out::println);}
其他以条件构造器为参数的方法
@Testvoid selectByWrapperMaps() {/** 使用场景:* 1.当表特别的多色时候只要查少数 几列,返回一个map,而不是属性大部分都为空的实体* 2.返回的是统计结果* 按照直属上级分组,查询每组的 平均年龄、最小龄、最大年龄。* 并且只取年龄总和小于500的组。* select* avg(age) avg_age,* min(age) min_age,* max(age) max_age* from user* group by manager_id --上级id分组* having sum(age) <500 --只有总和小于500* */// 第一种情况// query.like("name","雨").lt("age",40).select("id","name");// 第二种情况query.select("avg(age) avg_age","min(age) min_age","max(age) max_age").groupBy("manager_id").having("sum(age) < {0}",500);List<Map<String, Object>> users = userMapper.selectMaps(query);users.forEach(System.out::println);}@Testvoid selectByWrapperObjs() {query.select("id","name").like("name","雨").lt("age",40);// 返回第一列的值 只返回一列的时候用List<Object> users = userMapper.selectObjs(query);users.forEach(System.out::println);}@Testvoid selectByWrapperCounts() {// 不能设置查询的列名了query.like("name","雨").lt("age",40);// 查总记录数Integer count = userMapper.selectCount(query);System.out.println(count);}@Testvoid selectByWrapperOne() {// 不能设置查询的列名了query.like("name","老金").lt("age",40);// 只返回一条数据User user = userMapper.selectOne(query);System.out.println(user);}
lambda条件构造器
@Testvoid selectLambda() {// 创建方式// QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();// LambdaQueryWrapper<User> userLambdaQueryWrapper1 = new LambdaQueryWrapper<>();LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();// 好处: 防止误写字段名// where name like '%雨%' and age<40// 前面是类名 后面是get方法,表示属性lambdaQueryWrapper.like(User::getName, "雨").lt(User::getAge, 40);List<User> users = userMapper.selectList(lambdaQueryWrapper);users.forEach(System.out::println);}@Testvoid selectLambda1() {/** 名字为王姓并且(年龄小于40或邮箱不为空)* name like '王%' and (age<40 or email is not null)*/LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();// 好处: 防止误写字段名// 前面是类名 后面是get方法,表示属性lambdaQueryWrapper.likeRight(User::getName,"王").and(lqw->lqw.lt(User::getAge,40).or().isNotNull(User::getEmail));List<User> users = userMapper.selectList(lambdaQueryWrapper);users.forEach(System.out::println);}@Testvoid selectLambda2() {/** 名字为王姓并且(年龄小于40或邮箱不为空)* name like '王%' and (age<40 or email is not null)*/// 3.0.7新增创建方式List<User> users = new LambdaQueryChainWrapper<>(userMapper).like(User::getName, "雨").ge(User::getAge, 20).list();users.forEach(System.out::println);}
使用条件构造器的自定义SQL
方式1,sql写在接口中
在mapper接口中自定义
public interface UserMapper extends BaseMapper<User> {// 参数的注解是固定的 ew 就是WRAPPER的值@Select("select * from user ${ew.customSqlSegment}")List<User> selectAll(@Param(Constants.WRAPPER) Wrapper<User> wrapper);}
测试类
@Testvoid selectAllCustomize() {// 自定义的方法LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();lambdaQueryWrapper.likeRight(User::getName,"王").and(lqw->lqw.lt(User::getAge,40).or().isNotNull(User::getEmail));List<User> users = userMapper.selectAll(lambdaQueryWrapper);users.forEach(System.out::println);}
方式2,sql写在mapper中
在配置文件中配置接口对应的mapper文件
#设置扫描路径mybatis-plus.mapper-locations=mapper/*.xml
在resources下建mapper包
省略图
创建xml文件 UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.jsc.mybatisplus.mapper.UserMapper"><select id="selectAll" resultType="com.jsc.mybatisplus.entity.User"><!-- 参数的注解是固定的 ew 就是WRAPPER的值-->select * from user ${ew.customSqlSegment}</select></mapper>
接口中的sql注解就不用了
分页查询
首先明确一点,mybatis分页rowbounds确实实现了分页,但是是逻辑分页/内存分页,他先把数据全查出来,load到memory中,然后给你你想要的,换句话说,是海选...你懂我意思吧...可想而知,数据爆炸的时代,你得给多大的内存,内存不要钱吗,海选可贵,选择又多,多了换一批时间就 慢 ,一个道理~
Mp就提供了物理分页的插件,解决上述问题
既然是插件,肯定要配置
1.创建配置包 config
省略
2.创建配置类
package com.jsc.mybatisplus.config;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** mybatis的分页配置** @author 金聖聰* @version v1.0* @email jinshengcong@163.com* @date Created in 2021/04/16 15:48*/@Configurationpublic class MyBatisPlusConfig {// 新版废弃// @Bean// public PaginationInterceptor paginationInterceptor() {// return new PaginationInterceptor();// }//-------------------------------------------------/*未测试新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false避免缓存出现问题(该属性会在旧插件移除后一同移除)*//* @Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}@Beanpublic ConfigurationCustomizer configurationCustomizer() {return configuration -> configuration.setUseDeprecatedExecutor(false);}*///***************************************************/*** 注册插件* 依赖以下版本+* <dependency>* <groupId>com.baomidou</groupId>* <artifactId>mybatis-plus-boot-starter</artifactId>* <version>3.4.1</version>* </dependency>* @return com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor 拦截器* @author 金聖聰* @email jinshengcong@163.com* Modification History:* Date Author Description version*--------------------------------------------------------** 2021/04/16 15:56 金聖聰 修改原因 1.0*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {// 0.创建一个拦截器MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 1. 添加分页插件PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor();// 2. 设置请求的页面大于最大页后操作,true调回到首页,false继续请求。默认falsepageInterceptor.setOverflow(false);// 3. 单页分页条数限制,默认无限制pageInterceptor.setMaxLimit(500L);// 4. 设置数据库类型pageInterceptor.setDbType(DbType.MYSQL);// 5.添加内部拦截器interceptor.addInnerInterceptor(pageInterceptor);return interceptor;}}
3.测试类测试
@Testvoid selectPage() {//分页查询/** 1、名字中包含雨并且年龄小于40* name like '%雨%' and age<40* 条件构造器*/LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();lambdaQueryWrapper.ge(User::getAge,18);// 泛型是实体类 , 当前页数 默认是1,从1开始,不是0。每页最多多少条// 第一种用selectPage方法,返回的是 Page<User> userPage/*Page<User> page = new Page<>(1, 2);Page<User> userPage = userMapper.selectPage(page, lambdaQueryWrapper);System.out.println("总页数: "+userPage.getPages());System.out.println("总记录数: "+userPage.getTotal());userPage.getRecords().forEach(System.out::println);*/// 第二种用 selectMapsPage方法,返回的是 IPage<Map<String, Object>>// 如果第一个参数还是用的上面的page,此时page胡报错// 解决方案:// 把page 转成对应的类型IPage<Map<String, Object>>// 因为新版后(3.4.1+), 更改了源码 给他设定了具体类型IPage<Map<String, Object>> page1 = new Page<>(4, 2);IPage<Map<String, Object>> mapIPage = userMapper.selectMapsPage(page1, lambdaQueryWrapper);System.out.println("总页数: "+mapIPage.getPages());System.out.println("总记录数: "+mapIPage.getTotal());List<Map<String, Object>> records = mapIPage.getRecords();records.forEach(System.out::println);}
多表联查分页
实际开发中有的查询是多表联查的,这样就不能用上面的两个方法了,但是不甘心使用传统的写法,,那怎么办?
用xml自定义查询方法
在接口中创建自定义方法
// 自定义分页IPage<User> selectUserPage(Page<User> page,@Param(Constants.WRAPPER) Wrapper<User> wrapper);
xml中配置
<select id="selectUserPage" resultType="com.jsc.mybatisplus.entity.User"><!-- 参数的注解是固定的 ew 就是WRAPPER的值--><!-- 没有什么改变,但是可以自己多表联查-->select *from user ${ew.customSqlSegment}</select>
测试
@Testvoid selectPageCustomize() {//分页查询/** 1、名字中包含雨并且年龄小于40* name like '%雨%' and age<40* 条件构造器*/LambdaQueryWrapper<User> lambdaQueryWrapper = Wrappers.lambdaQuery();lambdaQueryWrapper.ge(User::getAge,18);// 泛型是实体类 , 当前页数 默认是1,从1开始,不是0。每页最多多少条// 第一种用selectPage方法,返回的是 Page<User> userPagePage<User> page = new Page<>(1, 2);IPage<User> userIPage = userMapper.selectUserPage(page, lambdaQueryWrapper);System.out.println("总页数: "+userIPage.getPages());System.out.println("总记录数: "+userIPage.getTotal());userIPage.getRecords().forEach(System.out::println);}
更新
根据id更新
@Testvoid UpdateById() {User user = new User();user.setId(1382713714941648898L);user.setName("小陈");int i = userMapper.updateById(user);System.out.println("影响记录数: "+i);}
以条件构造器作为参数的更新方法
private UpdateWrapper<User> update = Wrappers.update();@Testvoid UpdateByWrapper() {User user = new User();// user.setId(1382713714941648898L);user.setName("小金");update.eq("name","老金");int i = userMapper.update(user,update);System.out.println("影响记录数: "+i);}@Testvoid UpdateByWrapper1() {User whereUser = new User();// user.setId(1382713714941648898L);whereUser.setName("小金");// 可以直接把实体传进去update = new UpdateWrapper<>(whereUser);update.eq("age",18);User user = new User();user.setAge(21);int i = userMapper.update(user,update);System.out.println("影响记录数: "+i);}
条件构造器中set方法的使用
@Testvoid UpdateByWrapper2() {// 不创建实体传入,直接在条件中setupdate.eq("name","小金").set("name","老金");int i = userMapper.update(null,update);System.out.println("影响记录数: "+i);}
用lambda语法更新
@Testvoid UpdateByLambda() {LambdaUpdateWrapper<User> updateLambda = Wrappers.lambdaUpdate();updateLambda.eq(User::getName,"老金").set(User::getName,"小金");int i = userMapper.update(null,updateLambda);System.out.println("影响记录数: "+i);}@Testvoid UpdateByLambdaChain() {// 链式调用boolean update = new LambdaUpdateChainWrapper<User>(userMapper).eq(User::getName, "小金").set(User::getName, "老金").update();System.out.println(update?"成功":"失败");}
删除
根据id删除
@Testvoid deleteById() {int i = userMapper.deleteById(1382699085670719489L);System.out.println("影响行数: "+ i);}
其他普通方法删除
@Testvoid deleteByMap() {Map<String, Object> columnMap = new HashMap<>();columnMap.put("name","小金");columnMap.put("age","18");// WHERE name = ? AND age = ?int i = userMapper.deleteByMap(columnMap);System.out.println("影响行数: "+ i);}@Testvoid deleteByBatchIds() {List<Long> longs = Arrays.asList(1383035889074692097L, 1383035840634646530L);int i = userMapper.deleteBatchIds(longs);// WHERE id IN ( ? , ? )// 根据id批量删除System.out.println("影响行数: " + i);}
以条件构造器为参数的删除方法
@Testvoid deleteByWrapper() {LambdaQueryWrapper<User> lambdaQuery = Wrappers.lambdaQuery();lambdaQuery.eq(User::getId, "1383037094597267457");int delete = userMapper.delete(lambdaQuery);System.out.println("影响行数: " + delete);}
AR模式(ActiveRecord)
AR模式简介
活动记录,是一个领域模型模式,
特点:
一个模型类对应数据库中的一个表
模型类的一个实例对应表中的一个记录
简单来说就是通过实体类对象对表进行增删改查操作,方便开发人员的开发
MP中AR模式的实现
1.首先实体类要继承一个抽象类Model<泛型是这个类本身>
用lombok的@Data
后,继承别的类后会有个警告,用注解@EqualsAndHashCode(callSuper=false)
可以消除警告,再添加一个系列化id
````@EqualsAndHashCode(callSuper=false)``就是不调用父类,
但是,别的时候 大部分需要父类的一些属性作为等值比较的
@Data@EqualsAndHashCode(callSuper = false)public class User extends Model<User> {private static final long serialVersionUID = 7589930312778081895L;/** 主键 */private Long id;/** 姓名 */private String name;/** 年龄 */private Integer age;/** 邮件 */private String email;/** 直属上级id */private Long managerId;/** 创建时间 */private LocalDateTime createTime;}
2.必须存在原始mapper的接口,并继承baseMapper接口
@Testvoid ARInsertTest() {User user = new User();user.setName("xx");user.setAge(0);user.setManagerId(1088248166370832385L);user.setCreateTime(LocalDateTime.now());// 直接insert,自己插自己可还行boolean insert = user.insert();System.out.println(insert?"成功":"失败");}@Testvoid ARSelectByIdTest1() {// 不需要参数,直接实体上设置// 直接查,自己查自己可还行User user = new User();user.setId(1383044106274050049L);User user1 = user.selectById();System.out.println(user1);}// 查出来的都是新的对象,并没有把值设置到原来的对象上@Testvoid ARUpdateTest() {User user = new User();user.setId(1383044106274050049L);user.setName("xxoo");user.setAge(16);user.setManagerId(1383035808669888513L);user.setCreateTime(LocalDateTime.now());// 自己操作boolean b = user.updateById();System.out.println(b?"success":"fail");}@Testvoid ARDeleteTest() {User user = new User();user.setId(1383044106274050049L);// 自己操作boolean b = user.deleteById();System.out.println(b?"success":"fail");}
主键策略
MP支持的主键策略介绍
0.基于雪花算法(默认的)
1.局部主键策略实现
通过在实体类上id的注解@TableId(type=IdType.XXX)
设置
| 值 | 值 |
| AUTO | 数据库ID自增 |
| NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
| INPUT | insert前自行set主键值 |
| ASSIGN_ID | 分配ID(主键类型为Number(Long和Integer)或String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为 DefaultIdentifierGenerator雪花算法) |
| ASSIGN_UUID | 分配UUID,主键类型为String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认default方法) |
| ID_WORKER | 分布式全局唯一ID 长整型类型 (please use ASSIGN_ID) |
| UUID | 32位UUID字符串 (please use ASSIGN_UUID) |
| ID_WORKER_STR | 分布式全局唯一ID 字符串类型 (please use ASSIGN_ID) |
2.全局主键策略实现
在配置文件中设置
mybatis-plus.global-config.db-config.id-type=uuid
如果局部策略和全局策略都设置了 ,就近原则
MP配置
基本配置
基本的在官网,这里不做过多记录
https://mybatis.plus/config/#%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE
进阶配置
https://mybatis.plus/config/#configuration
mapUnderscoreToCamelCase
这个配置不能和configLocation
一起出现,会报错
字段验证策略
可以看一下~
不过一般都是默认的NOT_NULL
not_empty (字段为"")也是忽略
ignored 就是空的也插入 但是有风险 在更新的时候
但是在实体类中,
个别的,可以在字段上配置@TableField(stragegy=FieldStrategy.NOT_EMPTY)
,就是字段为""的时候也忽略
同样的就近原则
tablePrefix 表名前缀 全局设置
mybatis-plus.global-config.db-config.table-prefix=
通用Service
1.新建service包2.新建接口UserService
3.继承IService<T>
泛型写所对应的实体类4.创建service的实现包impl
5.创建UserServiceImp
6.继承ServiceImpl<UserMapper, User>
第一个蚕食数索要操作的mapper接口,第二个参数是对应的实体类7.实现刚才的接口UserService
,并给上@Service
的注解UserService.java
public interface UserService extends IService<User> {}ServiceImpl.java
@Servicepublic class UserServiceImp extends ServiceImpl<UserMapper, User> implements UserService{}基本方法
@Autowiredprivate UserService userService;@Testpublic void testService() {User one = userService.getOne(Wrappers.<User>lambdaQuery().gt(User::getAge,25),false);System.out.println(one);}
批量操作方法
@Testpublic void batchTest() {// 批量User user = new User();user.setName("犀利");user.setAge(12);User user1 = new User();user1.setName("犀利1");user1.setAge(121);List<User> users = Arrays.asList(user1, user);userService.saveBatch(users);}
链式调用方法
@Testpublic void chainTest() {// 查大于25的List<User> list = userService.lambdaQuery().gt(User::getAge, 25).list();list.forEach(System.out::println);}@Testpublic void chainTest1() {// 更新boolean update = userService.lambdaUpdate().eq(User::getName, "小陈").set(User::getName, "小玉").update();System.out.println(update?"success":"fail");}@Testpublic void chainTest2() {// 直接删除boolean update = userService.lambdaUpdate().eq(User::getName, "xx").remove();System.out.println(update?"success":"fail");}




