0


MyBatis-Plus——详解常用注解

📢📢📢📣📣📣

哈喽!大家好,我是【一心同学】,一位上进心十足的【Java领域博主】!😜😜😜

✨【一心同学】的写作风格:喜欢用【通俗易懂】的文笔去讲解每一个知识点,而不喜欢用【高大上】的官方陈述。

✨【一心同学】博客的领域是【面向后端技术】的学习,未来会持续更新更多的【后端技术】以及【学习心得】。

✨如果有对【后端技术】感兴趣的【小可爱】,欢迎关注一心同学】💞💞💞

❤️❤️❤️感谢各位大可爱小可爱!❤️❤️❤️


前言

本篇博客将详细介绍MyBatis-Plus中的常用注解以及其注意事项,并会对其常用的属性进行举例说明,而不常用的属性大家可根据描述信息进行了解。

一、@TableName

1.1 介绍

  • 描述:表名注解,映射数据库的表名

  • 使用位置:实体类

    属性值

属性类型必须指定默认值描述valueString否""表名schemaString否""schemakeepGlobalPrefixboolean否false是否保持使用全局的 tablePrefix 的值(当全局 tablePrefix 生效时)resultMapString否""xml 中 resultMap 的 id(用于满足特定类型的实体类对象绑定)autoResultMapboolean否false是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建与注入)excludePropertyString[]否{}需要排除的属性名 @since 3.3.1

1.2 使用

使用场景:当我们的实体类名跟我们的数据库表名不一致时,可根据@TableName来指定数据库表名。

例如:

我们的数据库表名是叫做person,但我们的Java实体类中却叫做User

解决映射冲突

添加注解@TableName(value = "person")

package com.yixin.mybatis_plus.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "person")
public class User {
    
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

二、@TableId

2.1 介绍

  • 描述:主键注解

  • 使用位置:实体类主键字段

    属性值

属性类型必须指定默认值描述valueString否""主键字段名typeEnum否IdType.NONE指定主键类型
IdType属性
值描述AUTO数据库自增NONE无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)雪花算法实现INPUT需要开发者手动赋值ASSIGN_IDMP 分配 ID,Long、Integer、StringASSIGN_UUID分配 UUID,Strinig
我们讲解在IdType中两个最常见的属性:AUTOINPUT

2.2 AUTO属性

  • 使用前提:需要在数据库中将主键设置为自增
  • 生成ID算法:【雪花算法】,基本可以保证全球唯一ID值。
  • 特点:生成的ID值在原来的ID基础上自增,并且会将ID值回填到我们的Java对象中。

注意:对主键使用了AUTO,那么我们自行注入的ID值将会被自动生成的ID覆盖

代码演示:

package com.yixin.mybatis_plus.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

测试:

我们在插入时自定义ID值

    @Test
    void test4() {

        // 我们没有自定义id,它会帮我们自动生成id
      Person person =new Person();
      person.setId(2L);
      person.setName("一心同学");
      person.setAge(18);
      person.setEmail("[email protected]");

      int result=personMapper.insert(person);

      System.out.println(result);// 受影响的行数

         System.out.println(person);//可以发现,id会自动回填
    }

结果:

发现1可以发现MP并没有采纳我们的ID值,因为其注入语句中根本就没有我们的主键id,而是选择用【雪花算法】自动生成的ID值。

发现2自动生成的ID值自动回填到我们的Java对象中了。

2.3 INPUT属性

生成ID算法:【雪花算法】,基本可以保证全球唯一ID值。

特点开发者没有手动赋值,则数据库通过自增的方式给主键赋值,如果开发者手动赋值,则存入该值。

注意:并不会回填到我们的Java对象中。

代码演示:

package com.yixin.mybatis_plus.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    @TableId(type = IdType.INPUT)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

(1)自定义ID测试

    @Test
    void test4() {

     //我们自定义ID,则会使用我们的ID,否则自动生成ID
      Person person =new Person();
      person.setId(5L);
      person.setName("一心同学2");
      person.setAge(18);
      person.setEmail("[email protected]");

      int result=personMapper.insert(person);

      System.out.println(result);// 受影响的行数

         System.out.println(person);
    }

结果:可以发现,MP是采用我们自定义的ID值的

(2)不定义ID值测试

    @Test
    void test4() {

     //我们自定义ID,则会使用我们的ID,否则自动生成ID
      Person person =new Person();
      person.setName("一心同学3");
      person.setAge(18);
      person.setEmail("[email protected]");

      int result=personMapper.insert(person);

      System.out.println(result);// 受影响的行数

         System.out.println(person);//发现不会回填!
    }

结果:可以发现,当我们没有进行ID的定义时,MP将会通过自增的方式给主键赋值,并且不会将赋完的值注入到我们的Java对象。

但在我们数据库中是有Id值的,只是没回填到Java对象而已。

2.4 AUTO与INPUT对比

AUTO与INPUT对比
Type算法特点是否覆盖自定义值是否回填AUTO雪花算法生成的ID值在原来的ID基础上自增是是INPUT雪花算法开发者没有手动赋值,则数据库通过自增的方式给主键赋值,如果开发者手动赋值,则存入该值。否否

三、@TableField

3.1 介绍

描述:字段注解(非主键)

属性值
属性类型必须指定默认值描述valueString否""数据库字段名existboolean否true是否为数据库表字段conditionString否""字段

where

实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的

%s=#{%s}

,参考(opens new window)updateString否""字段

update set

部分注入,例如:当在version字段上注解

update="%s+1"

表示更新时会

set version=version+1

(该属性优先级高于

el

属性)insertStrategyEnum否FieldStrategy.DEFAULT举例:NOT_NULL

insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)

updateStrategyEnum否FieldStrategy.DEFAULT举例:IGNORED

update table_a set column=#{columnProperty}

whereStrategyEnum否FieldStrategy.DEFAULT举例:NOT_EMPTY

where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>

fillEnum否FieldFill.DEFAULT字段自动填充策略selectboolean否true是否进行 select 查询keepGlobalFormatboolean否false是否保持使用全局的 format 进行处理jdbcTypeJdbcType否JdbcType.UNDEFINEDJDBC 类型 (该默认值不代表会按照该值生效)typeHandlerClass<? extends TypeHandler>否UnknownTypeHandler.class类型处理器 (该默认值不代表会按照该值生效)numericScaleString否""指定小数点后保留的位数
FieldStrategy 属性
值描述IGNORED忽略判断NOT_NULL非 NULL 判断NOT_EMPTY非空判断(只对字符串类型字段,其他类型字段依然为非 NULL 判断)DEFAULT追随全局配置
FieldFill属性值
值描述DEFAULT默认不处理INSERT插入时填充字段UPDATE更新时填充字段INSERT_UPDATE插入和更新时填充字段

看到上面这么多属性,是不是突然就了,不要怕!【一心同学】在这里,对于上面的属性,在我们开发中一些是不常用的,【一心同学】在这里用代码演示几个常见的属性,大家务必掌握。

3.2 普通属性

代码演示:

package com.yixin.mybatis_plus.pojo;

import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "person")
public class User {
    @TableId(type=IdType.AUTO)
    private Long id;

    // 当该字段名称与数据库名字不一致
    @TableField(value = "name")
    private String name;

    // 不查询该字段
    @TableField(select = false)
    private Integer age;

      // 是否为数据库表字段,设置为false,则插入时不会对其操作
    @TableField(exist = false)
    private String email;

    

}

3.3 自动填充属性

步骤一数据库增加两个属性,create_timeupdate_time。

步骤二:实体类字段属性添加注解。

    // 第一次添加填充
    @TableField(fill= FieldFill.INSERT)
    private Date createTime;

    // 第一次添加的时候填充,但之后每次更新也会进行填充
    @TableField(fill=FieldFill.INSERT_UPDATE)
    private Date updateTime;

步骤三:编写处理器来处理这个注解

注意:在处理器类上方添加注解@Component!

package com.yixin.mybatis_plus.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Slf4j
@Component // 一定不要忘记把处理器加到IOC容器中!
public class MyMetaObjectHandler implements MetaObjectHandler {
    // 插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill.....");
        // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject
        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);
    }
}

测试:

    @Test
    void test9() {

        // 我们没有自定义id,它会帮我们自动生成id
        User person =new User();
        person.setName("一心同学呀");
        person.setAge(20);
        person.setEmail("[email protected]");

        int result=personsMapper.insert(person);

        System.out.println(result);// 受影响的行数

        System.out.println(person);//可以发现,id会自动回填
    }

数据库

四、乐观锁

4.1 介绍

乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,再次更新值测试

悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

乐观锁实现方式:

取出记录时,获取当前 version

更新时,带上这个version

执行更新时, set version = newVersion where version = oldVersion

如果version不对,就更新失败

代码解释:

乐观锁:1、先查询,获得版本号 version = 1
-- A

update person set name = "yixin", version = version + 1
 where id = 2 and version = 1

-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败!
update person set name = "yixin", version = version + 1 
where id = 2 and version = 1

4.2 注意事项

  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity 中
  • 仅支持 updateById(id) 与 update(entity, wrapper) 方法
  • 在 update(entity, wrapper) 方法下, wrapper 不能复用

4.3 实现乐观锁

步骤一:给数据库中增加version字段!

步骤二:实体类添加对应的字段。

package com.yixin.mybatis_plus.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {

    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
    
    @Version //乐观锁Version注解
    private Integer version;
}

步骤三:注册组件。

package com.yixin.mybatis_plus.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

// 扫描我们的 mapper 文件夹
@MapperScan("com.yixin.mybatis_plus.mapper")
@EnableTransactionManagement
@Configuration // 配置类
public class MyBatisPlusConfig {

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

}

4.4 测试

(1)测试乐观锁成功情况

    @Test
    void testOptimisticLocker() {

        // 1、查询用户信息
       Person person=personMapper.selectById(1L);

        // 2、修改用户信息
        person.setName("一心同学");

        int result=personMapper.updateById(person);

        System.out.println(result);// 受影响的行数
    }

结果:****可以发现MP会自动帮我们进行乐观锁判定。

并且每修改一次,version就会+1。

(2)测试失败情况!多线程下!

    @Test
    void testOptimisticLocker2() {

        // 线程 1
        Person person=personMapper.selectById(3L);
        person.setName("一心同学在写博客");

        // 模拟另外一个线程执行了插队操作
        Person person2=personMapper.selectById(3L);
        person2.setName("一心同学在吃饭");

        personMapper.updateById(person2);

        int result=personMapper.updateById(person);// 如果没有乐观锁就会覆盖插队线程的值!

        System.out.println(result);// 受影响的行数
    }

数据库:

也就是说我们的线程一没有执行成功

五、逻辑删除

5.1 介绍

物理删除 :从数据库中直接移除

逻辑删除 :再数据库中没有被移除,而是通过一个变量来让他失效! deleted = 0 => deleted = 1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

5.2 实现逻辑删除

步骤一:在数据表中增加一个 deleted 字段。

步骤二:实体类中增加属性。

  @TableLogic //逻辑删除private 
     Integer deleted;

步骤三:配置。

(1)在自定义配置类中添加逻辑删除组件

package com.yixin.mybatis_plus.config;

import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

// 扫描我们的 mapper 文件夹
@MapperScan("com.yixin.mybatis_plus.mapper")
@EnableTransactionManagement
@Configuration // 配置类
public class MyBatisPlusConfig {

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

    // 逻辑删除组件!
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }

}

(2)在application.properties添加配置

# 配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

5.3 测试

    @Test
    void test6() {
        int result=personMapper.deleteById(5L);

        System.out.println(result);// 受影响的行数
    }

结果:

数据库:

数据库中并没有删除,而是将deleted从0变为1,实现了逻辑删除。(其实就是更新操作)


小结

以上就是【一心同学】整理的【MyBatis-Plus】的常用【注解】讲解,通过介绍和代码实现,相信大家基本已经掌握了,这一块的内容在我们平时的开发当中还是比较重要的,因为我们在开发当中用得最多的就是注解了,并且其能够大大提高我们的【工作效率】。

如果这篇【文章】有帮助到你,希望可以给【一心同学】点个👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【后端技术】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【一心同学】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!


本文转载自: https://blog.csdn.net/Huang_ZX_259/article/details/122516135
版权归原作者 一心同学 所有, 如有侵权,请联系我们删除。

“MyBatis-Plus&mdash;&mdash;详解常用注解”的评论:

还没有评论