Spring learning - MyBatisPlus use

Standard CRUD writing

lombok

  • Lombok, a Java class library, provides a set of annotations to simplify the development of POJO entity classes

  • Eliminate the writing of getter/setter/toString

  1. import dependencies
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>
  1. Add the @Data annotation before the entity class
@Data
@TableName(value = "tb_user")
public class User {
    
    
    private int id;
    private String name;
    private String password;
    private int age;
    private String tel;
}

Standard CRUD

  • query all
@Test
void testGetAll() {
    
    
    List<User> users = userDao.selectList(null);
    users.forEach(System.out::println);
}
  • query by id
@Test
void testGetById() {
    
    
    User user = userDao.selectById(1);
    System.out.println(user);
}
  • delete by id
@Test
void testDeleteById() {
    
    
    userDao.deleteById(2);
} 
  • renew
@Test
void testUpdateById() {
    
    
    User user = new User();
    user.setId(1);
    user.setName("jihua");
    userDao.updateById(user);//只修改提供的字段,不提供的不会修改为NULL
}

Paging query

  1. Set the paging interceptor as a bean managed by Spring (new configuration class)
@Configuration
public class MybatisPlusConfig {
    
    
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
    
    
        //1.定义MybatisPlus拦截器
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        //2.添加具体拦截器
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}
  1. Execute paging query
@Test
void testGetByPage() {
    
    
    IPage page = new Page(1,2);
    userDao.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());
}
  • Logs about opening MybatisPlus (in the configuration file application.yml)
# 开启日志,输出到控制台
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

DQL programming control

conditional query

  • MyBatisPlus encapsulates the writing of complex SQL query conditions, and completes the combination of query conditions in the form of programming

Conditional query - set query conditions

Format 1: regular format

//格式一:常规格式
@Test
void testWrapperGet1(){
    
    
    QueryWrapper<User> qw = new QueryWrapper<User>();
    //查询年龄大于等于18,小于60岁的用户
    qw.lt("age",60);
    qw.ge("age",18);
    List<User> users = userDao.selectList(qw);
    users.forEach(System.out::println);
}

Format 2: Chain programming format

//格式二:链式编程格式
@Test
void testWrapperGet2(){
    
    
    QueryWrapper<User> qw = new QueryWrapper<User>();
    //查询年龄大于等于18,小于60岁的用户
    qw.lt("age",60).ge("age",18);
    List<User> users = userDao.selectList(qw);
    users.forEach(System.out::println);
}

Format 3: lambda format (recommended)

//格式三:lambda格式(推荐)
@Test
void testWrapperGet3(){
    
    
    QueryWrapper<User> qw = new QueryWrapper<User>();
    //查询年龄大于等于18,小于60岁的用户
    qw.lambda().lt(User::getAge,60).ge(User::getAge,18);
    List<User> users = userDao.selectList(qw);
    users.forEach(System.out::println);
}

Format 4: lambda format

//格式四:lambda格式
@Test
void testWrapperGet4(){
    
    
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    //查询年龄大于等于18,小于60岁的用户
    lqw.lt(User::getAge,60).ge(User::getAge,18);
    List<User> users = userDao.selectList(lqw);
    users.forEach(System.out::println);
}

Conditional query - combined conditions

Combined conditions and

//条件查询——组合条件and
@Test
void testWrapperAnd(){
    
    
    LambdaQueryWrapper<User> lqw= new LambdaQueryWrapper<User>();
    //查询年龄大于等于18,小于60岁的用户
    lqw.lt(User::getAge,60).ge(User::getAge,18);
    List<User> users = userDao.selectList(lqw);
    users.forEach(System.out::println);
}

Combined conditions or

//条件查询——组合条件or
@Test
void testWrapperOr(){
    
    
    LambdaQueryWrapper<User> lqw= new LambdaQueryWrapper<User>();
    //查询年龄小于等于18,或大于60岁的用户
    lqw.gt(User::getAge,60).or().le(User::getAge,18);
    List<User> users = userDao.selectList(lqw);
    users.forEach(System.out::println);
}

Conditional query - null value determination

Use if statement to control conditional appending

@Test
void testWrapperNull() {
    
    
    UserQuery user = new UserQuery();
    user.setAge(18);//下限
    //user.setAge2(40);//上限
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
    if(null != user.getAge()){
    
    
        lqw.gt(User::getAge,user.getAge());
    }
    if(null!=user.getAge2()){
    
    
        lqw.lt(User::getAge,user.getAge2());
    }
    List<User> users = userDao.selectList(lqw);
    users.forEach(System.out::println);
}

Condition parameter control

@Test
void testWrapperNull() {
    
    
    UserQuery user = new UserQuery();
    user.setAge(18);//下限
    //user.setAge2(40);//上限
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
    lqw.gt(null != user.getAge(),User::getAge,user.getAge())
        .lt(null!=user.getAge2(),User::getAge,user.getAge2());
    List<User> users = userDao.selectList(lqw);
    users.forEach(System.out::println);
}

query projection

Query Projection - General

//查询投影——常规
@Test
void testSelect() {
    
    
    QueryWrapper<User> qw = new QueryWrapper<>();
    qw.select("name", "age", "tel");
    List<User> users = userDao.selectList(qw);
    users.forEach(System.out::println);
}

Query projection - lambda

//查询投影——lambda
@Test
void testSelectLambda() {
    
    
    LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
    lqw.select(User::getName, User::getAge, User::getTel);
    List<User> users = userDao.selectList(lqw);
    users.forEach(System.out::println);
}

Query conditions

eq match

LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.eq(User::getName, userQuery.getName()).eq(User::getPassword, userQuery.getPassword());
User loginUser = userDao.selectOne(lqw);
System.out.println(loginuser);

le, ge match, between match

LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
//方案一:设定上限下限
lqw.le(User::getAge, userQuery.getAge()).ge(User::getAge, userQuery.getAge2());
//方案二:设定范围
lqw.between(User::getAge, userQuery.getAge( ), userQuery.getAge2( ));

List<User> userList = userDao.selectList(lqw);
System.out.println(userList);

like match

LambdaQuerywrapper<User> fqw = new LambdaQuerywrapper<User>();
lqw.likeLeft(User::getTel, userQuery.getTel());
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
  • like match
    • like(name, "R"):%R%
    • likeLeft(name, "R"):R%
    • likeRight(name, "R"):%R

Group statistics query

  • When using count(*)statistical queries, the query should useselectMaps()
//分组统计查询
@Test
void testSelectGroup() {
    
    
    QueryWrapper<User> qw = new QueryWrapper<>();
    qw.select("count(*) as 人数", "age");
    qw.groupBy("age");
    List<Map<String, Object>> mapList = userDao.selectMaps(qw);
    mapList.forEach(System.out::println);
}

Field mapping and table name mapping

@TableName("tbl_user")//将实体类与表名映射
public class User {
    
    
    private Long id;
    @TableField(value="pwd")//将实体类的属性和表的列名对应
    private String name;
    @TableField(select = false)//设置属性不参与查询 
    private string password;
    private Integer age;
    private String tel;
    @TableField(exist = false)//设置属性在表中是否存在
    private Integer online;
}

  • name: @TableField

  • Type: Attribute Annotation

  • Location: Above the model class attribute definition

  • Function: Set the field relationship in the database table corresponding to the current attribute

  • example:

    public class User {
          
          
        private Long id;
        @TableField(value="pwd")//将实体类的属性和表的列名对应
        private String name;
        @TableField(select = false)//设置属性不参与查询 
        private string password;
        private Integer age;
        private String tel;
        @TableField(exist = false)//设置属性在表中是否存在
        private Integer online;
    }
    
  • related attributes

    • value: Set the database table field name
    • exist: Set whether the attribute exists in the database table field, the default is true. This attribute cannot be combined with value
    • select: Whether to set the attribute to participate in the query, this attribute does not conflict with the select() mapping configuration

  • Name: @TableName

  • Type: class annotation

  • Location: above the model class definition

  • Role: Set the relationship between the current class and the database table

  • example:

    @TableName("tbl_user")//将实体类与表名映射
    public class User {
          
          
        ...
    }
    
  • related attributes

    • value: set the database table name

DML programming control

insert

id generation policy control

  • Different tables apply different id generation strategies
    • log: increment(1,2,3,4,…)
    • Shopping Orders: Special Rules (FQ23948AK3843)
    • Takeaway order: related area date and other information (10 04 20200314 34 91)
    • Relational table: id can be omitted

  • Name: @TableId

  • Type: Attribute Annotation

  • Location: above the definition of the property used to represent the primary key in the model class

  • Role: Set the generation strategy of the primary key attribute in the current class

  • example:

    public class User {
          
          
    	@TableId(type = IdType.AUTO)
        private Long id;
    }
    
  • related attributes

    • value: Set the database primary key name
    • type: Set the generation strategy of the primary key attribute, the value refers to IdTypethe enumeration value

  • AUTO(0): Use the database id self-increment strategy to control id generation
  • NONE(1): Do not set the id generation strategy
  • INPUT(2): The user manually enters the id
  • ASSIGN_ID(3): Snowflake algorithm generates id (compatible with numeric and string types)
  • ASSIGN_UUID(4): Use the UUID generation algorithm as the id generation strategy

global configuration

in application.yml

mybatis-plus:
  global-config:
    db-config:
      #配置id生成策略
      id-type: auto
      #配置表名前缀(即表名在实体类名称前面加的前缀)
      table-prefix: tbl_

delete

multi-record operation

  • Delete multiple records by primary key
List<Long> ids= Arrays.asList(new Long[ ]{
    
    2,3});
userDao.deleteBatchIds(ids);
  • Query multiple records based on primary key
List<Long> ids= Arrays.asList(new Long[]{
    
    2,3});
List<User> userList = userDao.selectBatchIds(ids);

Tombstone

  • Logical deletion means not deleting data when performing a delete operation, but marking the data as deleted

step:

  1. Add logical delete flag field to database table

    • Add a field named deleted to the database table, set the default value to 0
  2. Add the corresponding field to the entity class, and set the current field as the logical deletion mark field

    public class User {
          
          
    	private Long id;
        @TableLogic(value = "0", delval = "1")//配置逻辑删除,0为未删除,1为已删除
    	private Integer deleted;
    }
    
  3. You can also do global tombstone configuration in the configuration (application.yml)

    mybatis-plus:
      global-config:
        db-config:
          #配置逻辑删除字段名
          logic-delete-field: deleted
          #配置未删除时的值
          logic-not-delete-value: 0
          #配置已删除的值
          logic-delete-value: 1
    
  • Once the tombstone function is enabled, the delete statement will become an update statement (not delete but update whose deleted value is 1)

  • The query operation will also automatically add the condition where deleted = 0

  • To query all attributes, you need to write your own SQL statement to query

optimistic lock

Add the lock tag field version to the database table. When operating data, first query the current version. When performing the operation, compare the queried version with the version in the current table (to prevent the data from being modified by other threads). After performing the operation, the version+1

  1. Add a lock tag field version to the database table

  2. Add the corresponding field to the entity class, and set the current field as the logical deletion mark field

    public class User {
          
          
    	private Long id;
        @Version
    	private Integer version;
    }
    
  3. Configure the optimistic lock interceptor to realize the dynamic SQL statement assembly corresponding to the lock mechanism

    @Configuration
    public class MybatisPlusConfig {
          
          
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
          
          
            //1.定义MybatisPlus拦截器
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            //2.添加乐观锁拦截器
            mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return mybatisPlusInterceptor;
        }
    }
    
  4. Using the optimistic locking mechanism, the verion of the corresponding data must be obtained before the modification can be performed normally

    @Test
    void testUpdate(){
          
          
    	//先查询数据,获取到version数据
    	User user = userDao.selectById(1L);
        User user1 = userDao.selectById(1L);
        //执行数据修改操作
        //操作一
    	user.setName("Tom and Jerry");
        userDao.updateById(user);
        //操作二
        user1.setName("6666");
        userDao.updateById(user1);
    }//此时操作二将不会执行成功
    
    • Execute the query statement before executing the modification:

      SELECT id,name,age,tel,deleted,version FROM tbl_user WHERE id=?
      
    • Use the version field as the basis for optimistic lock checking when performing modifications

      UPDATE tbl_user SET name=?, age=?, tel=?, version=? WHERE id=? AND version=?
      

Guess you like

Origin blog.csdn.net/jihuaTEL/article/details/129653969