MybatisPlus
# 基本使用
导入依赖坐标
<!-- 引入 mybatis -plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency>继承父类
@Mapper public interface UserMapper extends BaseMapper<User> { }测试(修改方式见下方 设置映射)
- 默认表名是 user——>实体类的小写
- 默认是下划线命名
pojo——>private String phoneNum- 数据库的列名——> 对应列名为phone_num
@SpringBootTest class MybatisplusApplicationTests { @Autowired private UserMapper userMapper; @Test void testAll() { List<User> users = userMapper.selectList(null); System.out.println(users); } }MyBatisPlus特性

CRUD
增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)

# 标准开发
# 插入
@Test //插入
void testSave() {
User user=new User();
user.setUsername("皎月女神");
user.setPassword("169384");
user.setEmail("123@123.com");
user.setPhoneNum("177");
//调用插入操作
userMapper.insert(user);
}
# 删除
按id删除一个
@Test //删除 void testDelete() { //调用删除操作 // userMapper.deleteById("1519198458484707330");//字符串 userMapper.deleteById(1519198458484707330L); //long类型 }删除一组
@Test // 多条删除 void testDeleteSome() { List<Integer> list=new ArrayList<Integer>(); list.add(17); list.add(18); list.add(20); userMapper.deleteBatchIds(list); }
# 逻辑删除
通过一个特殊字段的值来判断是否删除,并不真正删除数据 —— 设置为deleted
- 千万不要设置成
delete,会影响sql语句
- 千万不要设置成
设置为逻辑删除值 —— 一个是使用注解,一个是配置了全局设置
//逻辑删除字段,标记当前记录是否被删除 @TableLogic(value = "0",delval = "1") //value-0表示 没有被删除 delval-1 表示被删除 private int deleted;db-config: id-type: assign_id #设置主键id 自增策略 table-prefix: tb_ #设置表的前缀 logic-delete-field: deleted #设置代表逻辑删除的列名 logic-delete-value: 0 #不删除的数据 deleted为0 logic-not-delete-value: 1 # 删除的数据 deleted为1删除语句的MP执行sql
UPDATE tb_user SET deleted=1 WHERE id=? AND deleted=0
查询语句的MP执行sql
SELECT id,age,username,email,phone_num,deleted FROM tb_user WHERE id=? AND deleted=0
# 更新
方式1
//更新方法1 带上要修改的id,带上版本号, 带上要修改的数据字段 User user=new User(); user.setId(2L); user.setVersion(1); //乐观锁必带这个属性 user.setUsername("阿波尼亚"); //要修改的字段 //调用更新操作 根据id修改值 userMapper.updateById(user);方式2 —— 带乐观锁 更推荐第二种
//更新方法2 根据要修改的id 查询出对象来,这样查询出来的数据一定带着乐观锁的版本号,就不用自己手动设置了 User user=userMapper.selectById(2L); user.setUsername("阿波尼亚妈妈"); userMapper.updateById(user);
# 乐观锁
通过一个特殊字段的值来实现小规模的并发访问控制—— version
UPDATE tb_user SET username=?, version=? WHERE id=? AND version=? AND deleted=1阿波尼亚(String), 2(Integer), 2(Long), 1(Integer)
乐观锁拦截器
//2.2添加乐观锁拦截器 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());多用户并发访问处理
当用户1 修改这个对象时,version=4,成功修改,数据库乐观锁 version=5

当用户2同时修改这个对象时,自身携带的version=4,但是数据库的乐观锁version=5,所以修改失败

# 查询
按id查询单个
@Test //查询单个 void testOne() { User user =userMapper.selectById(2); System.out.println(user); }按ids查询一组
@Test // 多条查询 void testSelectSome() { List<Integer> list=new ArrayList<Integer>(); list.add(11); list.add(15); list.add(16); userMapper.selectBatchIds(list); }查询全部
@Test //查询全部 void testAll() { List<User> users = userMapper.selectList(null); System.out.println(users); }
# 分页查询
方法使用
@Test //分页查询 需要开启拦截器 void testGetPage() { IPage page=new Page(2,2);//当前页,每页条数 userMapper.selectPage(page,null); System.out.println("当前页码值:"+page.getCurrent()); System.out.println("每页显示数:"+page.getSize()); System.out.println("一共多少页:"+page.getPages()); System.out.println("一共多少条数据:"+page.getTotal()); System.out.println("查询数据:"+page.getRecords()); }拦截器配置
@Configuration public class MpConfig { @Bean public MybatisPlusInterceptor pageInterceptor(){ //1.定义Mp拦截器 MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor(); //2.添加分页拦截器 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }Mp 日志开启
#开启mp日志 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 条件查询
方式1
@Test//方式1 按条件查询 void testGetAll() { QueryWrapper qw =new QueryWrapper(); qw.lt("id","12"); //小于 qw.gt("id","5"); //大于 List<User> users = userMapper.selectList(qw); //大于5,小于12 System.out.println(users); }方式2
@Test//方式2 lambda 格式按条件查询 void testGetAll2() { QueryWrapper<User> qw =new QueryWrapper<User>(); qw.lambda().lt(User::getId,12); //小于 qw.lambda().gt(User::getId,5); //大于 List<User> users = userMapper.selectList(qw); //大于5,小于12 System.out.println(users); }方式3 ——>推荐
@Test//方式3 lambda 格式按条件查询 推荐使用 void testGetAll3() { LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>(); //一般多条件查询 // lqw.lt(User::getId,12); //小于 // lqw.gt(User::getId,5); //大于 //链式编程 多条件查询 并且 and //大于5且小于12 // lqw.lt(User::getId,12).gt(User::getId,5); //链式编程 多条件查询 或者 or //大于12或者小于5 lqw.lt(User::getId,5).or().gt(User::getId,12); List<User> users = userMapper.selectList(lqw); System.out.println(users); }链式编程法则
书写 ——>
and//链式编程 多条件查询 并且 and //大于5且小于12 lqw.lt(User::getId,12).gt(User::getId,5);书写 ——>
or//链式编程 多条件查询 或者 or //大于12或者小于5 lqw.lt(User::getId,5).or().gt(User::getId,12);
条件查询null值判断
int与Integer的区别- 详细区别 (opens new window)
- 简单说明
int,是基本数据类型,默认值为0,可以直接使用;不赋值,默认就是0Integer,是int的封装类,是一个对象,默认值是null,需要实例化才能使用,实例化就是赋值,不赋值就是null。
使用if判断条件
//NULL 判定 LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>(); lqw.lt(User::getAge,uq.getAge2()); if(uq.getAge() !=null){ lqw.gt(User::getAge,uq.getAge()); }使用方法内置条件
链式编程,长度不要超过一行,打回车即可,点好尽量对齐
//NULL 判定 LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>(); //多个条件 //lqw.lt(uq.getAge2()!=null,User::getAge,uq.getAge2()); //lqw.gt(uq.getAge() !=null,User::getAge,uq.getAge()); //链式 lqw.lt(uq.getAge2()!=null,User::getAge,uq.getAge2()) .gt(uq.getAge() !=null,User::getAge,uq.getAge());
# 查询投影
设置查询字段
QueryWrapper与LambdaQueryWrapper都可以使用@Test//查询投影----设置查询字段 void testSelect1() { QueryWrapper<User> qw =new QueryWrapper<User>(); qw.select("id","username","age"); //只查询这三个列,其他设为空 LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>(); lqw.select(User::getId,User::getAge,User::getUsername); //查询全部数据,限制列数 List<User> users = userMapper.selectList(lqw); System.out.println(users); }查询个数 只能用
QueryWrapper@Test//查询投影----查询个数 只能用 QueryWrapper void testSelect2() { QueryWrapper<User> qw =new QueryWrapper<User>(); //查询全部 // qw.select("count(*) as count"); //分组查询 qw.select("count(*) as count,password"); qw.groupBy("password"); //查询个数 List<Map<String, Object>> maps = userMapper.selectMaps(qw); System.out.println(maps); }
# 查询条件
等匹配
@Test//查询条件———— 等匹配 void testSelectCon1() { LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>(); //等同于 lqw.eq(User::getUsername,"diana").eq(User::getPassword,"456"); //md5加密 User user = userMapper.selectOne(lqw); System.out.println(user); }范围查询
@Test//查询条件———— 范围查询 void testSelectCon2() { LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>(); //范围查询 lt,gt; le,ge; between lqw.between(User::getAge,10,20); //between 两边都包括 List<User> users = userMapper.selectList(lqw); System.out.println(users); }模糊匹配
@Test//查询条件———— 模糊匹配 void testSelectCon3() { LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<User>(); //模糊匹配 like likeLeft likeRight lqw.likeRight(User::getUsername,"d"); List<User> users = userMapper.selectList(lqw); System.out.println(users); }
# 设置映射
设置表名映射
- 默认表名是 实体类的首字母小写,即
user,设置后为sys_user
@TableName("sys_user") public class User {}- 默认表名是 实体类的首字母小写,即
设置列名映射
- 数据库列名为
psd,实体类属性名为password, 使用value属性设置映射关系
@TableField(value = "psd",select = false) //设置当前属性对应的数据库表中的字段关系 //select 属性 设置是否参与查询 private String password;- 数据库列名为
设置是否参与查询
- 使用
select属性 设置是否参与查询
@TableField(value = "psd",select = false) //设置当前属性对应的数据库表中的字段关系 //select 属性 设置是否参与查询 private String password;- 使用
设置存在属性
- 一些属性,数据库中没有,但是实体类中有,要用
exist属性去声明下
@TableField(exist = false)//数据库中不存在,但是我实体类中定义了 private Integer online;- 一些属性,数据库中没有,但是实体类中有,要用
# ID 自增策略
// @TableId(type= IdType.AUTO) //按照数据库规则自动递增, +1
// @TableId(type= IdType.INPUT) //要求用户自己输入id
@TableId(type= IdType.ASSIGN_ID) //使用雪花算法,生成Long类型id 超长id
private Long id;

# 全局配置
设置了全局配置以后,就不用在对应的java代码上使用注解了
表的前缀,数据库表去掉前缀后,若剩余表名与数据库实体类名能对应上,就不需要使用
@TableName
db-config:
id-type: assign_id #设置主键id 自增策略
table-prefix: tb_ #设置表的前缀
logic-delete-field: deleted #设置代表逻辑删除的列名
logic-delete-value: 0 #不删除的数据 deleted为0
logic-not-delete-value: 1 # 删除的数据 deleted为1
#开启mp日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # sql查询语句及数据
global-config:
banner: false #禁止输出mybatisPlus的logo
db-config:
id-type: assign_id #设置主键id 自增策略
table-prefix: tb_ #设置表的前缀
logic-delete-field: deleted #设置代表逻辑删除的列名
logic-delete-value: 0 #不删除的数据 deleted为0
logic-not-delete-value: 1 # 删除的数据 deleted为1
# 实体类工具
导入依赖
<!-- 快速开发实体类--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency>使用方法
通过注解方式,来生成对应的方法,简化代码的书写
@Data//@Setter //@Getter //@ToString //@EqualsAndHashCode //equal方法和hashcode方法 @Data //等于上面一堆 不包含构造方法构造方法
@NoArgsConstructor //无参构造 @AllArgsConstructor //全参构造
# 代码生成器
导入依赖
<!-- 引入 代码生成器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4.0</version> </dependency> <!-- 引入模板引擎--> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.2</version> </dependency>代码生成器 步骤
//1.生成代码生成器 AutoGenerator autoGenerator=new AutoGenerator(); //2.配置代码生成器 ……………………………………………… //3.执行代码生成器 autoGenerator.execute();设置数据源
//2.1配置数据源 DataSourceConfig dataSource=new DataSourceConfig(); dataSource.setDriverName("com.mysql.cj.jdbc.Driver"); dataSource.setUsername("root"); dataSource.setPassword("1234"); dataSource.setUrl("jdbc:mysql:///test?useSSL=false&useServerPrepStmts=true"); autoGenerator.setDataSource(dataSource);设置全局配置
//2.2设置全局配置 GlobalConfig globalConfig = new GlobalConfig(); globalConfig.setOutputDir(System.getProperty("user.dir")+"/codeAuto/src/main/java"); //设置代码生成位置 globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录 globalConfig.setAuthor("diana"); //设置作者 globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件 globalConfig.setMapperName("%sMapper"); //设置数据层接口名,%s为占位符,指代模块名称 不加修改指表名 globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略 autoGenerator.setGlobalConfig(globalConfig);设置包名相关配置
//2.3设置包名相关配置 PackageConfig packageInfo = new PackageConfig(); packageInfo.setParent("com.liangbing"); //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径 packageInfo.setEntity("pojo"); //设置实体类包名 packageInfo.setMapper("mapper"); //设置数据层包名 autoGenerator.setPackageInfo(packageInfo);策略设置
//2.4策略设置 StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig.setInclude("tb_user"); //设置当前参与生成的表名,参数为可变参数 strategyConfig.setTablePrefix("tb_"); //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名 例如: User = tbl_user - tbl_ strategyConfig.setRestControllerStyle(true); //设置是否启用Rest风格 strategyConfig.setVersionFieldName("version"); //设置乐观锁字段名 strategyConfig.setLogicDeleteFieldName("deleted"); //设置逻辑删除字段名 strategyConfig.setEntityLombokModel(true); //设置是否启用lombok autoGenerator.setStrategy(strategyConfig);
生成的service 接口名称
IUserService使用I开头
