0
点赞
收藏
分享

微信扫一扫

Mybatis-Plus必会知识点(精美最全)


1首先说下引入

pom里面添加:
      <!--mybatis-plus-->
     <dependency>
         <groupId>com.baomidou</groupId>
         <artifactId>mybatis-plus-boot-starter</artifactId>
         <version>3.3.1</version>
     </dependency>yml添加:
 # 数据源
spring:
  datasource:
       username: root
       password: root
       url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
       driver-class-name: com.mysql.jdbc.Driver
  创建包 mapper 编写Mapper 接口:
 
 



     
   
 
   



public interface UserMapper extends BaseMapper<User> {
     ...........
}
 
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
例如:
  @SpringBootApplication
 @MapperScan("com.zx.mapper")
 public class MybatisPlusApplication {
     ......
 }




2MP的主键策略

1、ASSIGN_ID

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

  • 雪花算法:分布式ID生成器
  • 雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。
  • 核心思想:
  • 长度共64bit(一个long型)。
  • 首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0。
  • 41bit时间截(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截),结果约等于69.73年。
  • 10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。
  • 12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。

小项目我们用自增

AUTO 自增策略


  • 需要在创建数据表的时候设置主键自增
  • 实体字段中配置 @TableId(type = IdType.AUTO)

 

3自动填充

实体上增加字段并添加自动填充注解

@Data
 public class User {
     ......
         
     @TableField(fill = FieldFill.INSERT)
     private Date createTime;    //@TableField(fill = FieldFill.UPDATE)
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private Date updateTime;
 }实现MetaObjectHandler接口 重写   insertFill  和 updateFill      不要忘记@Component     | 这里的数据库是datetime类型   然后在实体类里面写 Date类型
package com.zx
@Slf4j
 @Component
 public class MyMetaObjectHandler implements MetaObjectHandler {    @Override
     public void insertFill(MetaObject metaObject) {
         log.info("start insert fill ....");
         this.setFieldValByName("createTime", new Date(), metaObject);
         this.setFieldValByName("updateTime", new Date(), metaObject);
     }    @Override
     public void updateFill(MetaObject metaObject) {
         log.info("start update fill ....");
         this.setFieldValByName("updateTime", new Date(), metaObject);
     }
 }

4乐观锁

 

1、场景

一件商品,成本价是80元,售价是100元。老板先是通知小李,说你去把商品价格增加50元。小李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太高,可能会影响销量。又通知小王,你把商品价格降低30元。

此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就完全被小王的覆盖了。

现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1多万。

2、乐观锁与悲观锁

  • 上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过了,则重新取出的被修改后的价格,150元,这样他会将120元存入数据库。
  • 如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证最终的价格是120元。

乐观锁实现流程

(1)修改实体类

添加 @Version 注解

      

         @Version
       
 
      

         
       
 
       
private Integer version;

(2)创建配置文件 

创建包config,创建文件MybatisPlusConfig.java
  
 
  
@MapperScan 扫描注解
  
 
  

      
    
 
    

       
     
 
    
package com.zx.config;
@EnableTransactionManagement
 @Configuration
 @MapperScan("com.zx.mapper")
 public class MybatisPlusConfig {
     
 }

 

(3)注册乐观锁插件

在 MybatisPlusConfig 中注册 Bean
 
  



      
    
 
    


           /**
      
      * 乐观锁插件
      
      */
      
 @Bean
      
 public OptimisticLockerInterceptor optimisticLockerInterceptor() {
      
     return new OptimisticLockerInterceptor();
      
 }


5查询

通过多个id批量查询

@Test
 public void testSelectBatchIds(){    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
     users.forEach(System.out::println);
 }

简单的条件查询

通过map封装查询条件

注意:map中的key对应数据库中的列名。如:数据库user_id,实体类是userId,这时map的key需要填写user_id

@Test
 public void testSelectByMap(){    HashMap<String, Object> map = new HashMap<>();
     map.put("name", "Helen");
     map.put("age", 18);
     List<User> users = userMapper.selectByMap(map);    users.forEach(System.out::println);
 }

6分页

分页插件

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

(1)添加分页插件

配置类中添加@Bean配置

/**
  * 分页插件
  */
 @Bean
 public PaginationInterceptor paginationInterceptor() {
     return new PaginationInterceptor();
 }

(2)selectPage实现分页

@Test
 public void testSelectPage() {    Page<User> page = new Page<>(1,5);
     Page<User> pageParam = userMapper.selectPage(page, null);    pageParam.getRecords().forEach(System.out::println);
     System.out.println(pageParam.getCurrent());
     System.out.println(pageParam.getPages());
     System.out.println(pageParam.getSize());
     System.out.println(pageParam.getTotal());
     System.out.println(pageParam.hasNext());
     System.out.println(pageParam.hasPrevious());
 }

返回指定列

Page<Map<String, Object>> page = new Page<>(1, 5);
     QueryWrapper<User> queryWrapper = new QueryWrapper<>();
     queryWrapper.select("name", "age");
     Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, queryWrapper);    List<Map<String, Object>> records = pageParam.getRecords();
     records.forEach(System.out::println);
     System.out.println(pageParam.getCurrent());
     System.out.println(pageParam.getPages());
     System.out.println(pageParam.getSize());
     System.out.println(pageParam.getTotal());
     System.out.println(pageParam.hasNext());
     System.out.println(pageParam.hasPrevious());

7删除

逻辑删除

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

1 添加 deleted字段

2 添加deleted 字段,并加上 @TableLogic 注解 

@TableLogic
 private Integer deleted;

3配置(可选)application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无

mybatis-plus.global-config.db-config.logic-delete-value=1
 mybatis-plus.global-config.db-config.logic-not-delete-value=0

根据id删除记录  

@Test
 public void testDeleteById(){    int result = userMapper.deleteById(5L);
     System.out.println(result);
 }

批量删除

@Test
 public void testDeleteBatchIds() {
    int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
     System.out.println(result);
 }

简单条件删除

@Test
 public void testDeleteByMap() {    HashMap<String, Object> map = new HashMap<>();
     map.put("name", "Helen");
     map.put("age", 18);deleteByMap(map);
     System.out.println(result);
 }

8条件构造器

一、wapper介绍 

@Test
 public void testSelectOne() {    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
     queryWrapper.eq("name", "张旭");    User user = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常
     System.out.println(user);
 }

3、between、notBetween

@Test
 public void testSelectCount() {    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
     queryWrapper.between("age", 20, 30);    Integer count = userMapper.selectCount(queryWrapper); //返回数据数量
     System.out.println(count);
 }

4、like、notLike、likeLeft、likeRight

selectMaps()返回Map集合列表,通常配合select()使用

@Test
 public void testSelectMaps() {    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
     queryWrapper
         .select("name", "age")
         .like("name", "e")
         .likeRight("email", "5");    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
     maps.forEach(System.out::println);
 }

5、in、notIn、inSql、notinSql、exists、notExists

in、notIn:
• notIn("age",{1,2,3})--->age not in (1,2,3)
• notIn("age", 1, 2, 3)--->age not in (1,2,3)
inSql、notinSql:可以实现子查询
• 例: inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)

• 例: inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)

  @Test
     public void testSelectObjs() {        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
 //        queryWrapper.in("id", 1, 2, 3);
         queryWrapper.inSql("id", "select id from user where id <= 3");        List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表
         objects.forEach(System.out::println);
     }

6、or、and

注意:这里使用的是 UpdateWrapper 

不调用or则默认为使用 and 连接

@Test
 public void testUpdate1() {    //修改值
     User user = new User();
     user.setAge(99);
     user.setName("Andy");    //修改条件
     UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
     userUpdateWrapper
         .like("name", "h")
         .or()
         .between("age", 20, 30);    int result = userMapper.update(user, userUpdateWrapper);
    System.out.println(result);
 }

7、lambda表达式

lambda表达式内的逻辑优先运算

@Test
 public void testUpdate2() {    //修改值
     User user = new User();
     user.setAge(99);
     user.setName("Andy");    //修改条件
     UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
     userUpdateWrapper
         .like("name", "n")
         .or(i -> i.like("name", "a").eq("age", 20));    int result = userMapper.update(user, userUpdateWrapper);
    System.out.println(result);
 }

8、orderBy、orderByDesc、orderByAsc

@Test
 public void testSelectListOrderBy() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
     queryWrapper.orderByDesc("age", "id");
    List<User> users = userMapper.selectList(queryWrapper);
     users.forEach(System.out::println);
 }

9、set、setSql

最终的sql会合并 user.setAge(),以及 userUpdateWrapper.set()  和 setSql() 中 的字段

@Test
 public void testUpdateSet() {    //修改值
     User user = new User();
     user.setAge(60);    //修改条件
     UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
     userUpdateWrapper
         .like("name", "h")
         .set("name", "Peter")//除了可以查询还可以使用set设置修改的字段
         .setSql(" email = '123@qq.com'");//可以有子查询    int result = userMapper.update(user, userUpdateWrapper);
 }

举报

相关推荐

0 条评论