20241009--Java--MyBatis-Plus常见注解(3)

一、 介绍

在第一节的笔记中,我们仅仅引入依赖,继承了一个 BaseMapper,就是实现了操纵数据库查询数据的目的。

那么MybatisPlus怎么知道我们要查的是数据库中的哪个表呢? 表中的字段是如何获取的呢?
接下来,就将介绍如何利用注解来联系数据库中表以及表的字段的。

二、常见注解

在第一节中我们的入门案例UserMapper接口继承了BaseMapper,同时泛型指定为了User。那么这个User类就是MP找到数据库表的关键。

MybatisPlus就是根据PO实体的信息来推断出表的信息,从而生成SQL的。默认情况下:

  • MybatisPlus会把PO实体的类名驼峰转下划线作为表名
  • MybatisPlus会把PO实体的所有变量名驼峰转下划线作为表的字段名,并根据变量类型推断字段类型
  • MybatisPlus会把名为id的字段作为主键

但很多情况下,默认的实现与实际场景不符,因此MybatisPlus提供了一些注解便于我们声明表信息。

1、@TableName

该注解用于指定实体类对应的数据库表名。当实体类名与数据库表名不一致,或者实体类名不是数据库表名的驼峰写法时,需要使用这个注解来明确指定表名。

@TableName("sys_user")     
public class User {     
    private Long id;     
    private String name;     
    private Integer age;     
    private String email;     
}
属性类型必须指定默认值描述
valueString“”表名
schemaString“”schema
keepGlobalPrefixbooleanfalse当全局配置了 tablePrefix 时,这个属性决定是否保持使用全局的表前缀。如果设置为 true,即使注解中指定了表名,也会自动加上全局的表前缀。
resultMapString“”指定在 XML 中定义的 ResultMap 的 ID,用于将查询结果映射到特定类型的实体类对象。
autoResultMapbooleanfalse是否自动构建 resultMap。如果已经设置了 resultMap,这个属性不会生效。

|excludeProperty|String [] | 否 | {} |指定在映射时需要排除的属性名。这些属性将不会被包含在生成的 SQL 语句中。@since 3.3.1|

2、@TableId

该注解用于标记实体类中的主键字段。如果你的主键字段名为 id,你可以省略这个注解。

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
属性类型必须指定默认值描述
valueString“”指定数据库表的主键字段名。如果不设置,MyBatis-Plus 将使用实体类中的字段名作为数据库表的主键字段名。
typeEnumIdType.NONE指定主键的生成策略。

IdType 枚举类型定义:

描述
AUTO数据库 ID 自增
NONE无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUTinsert 前自行 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 方法)

这里比较常见的有三种:

  • AUTO:利用数据库的id自增长
  • INPUT:手动生成id
  • ASSIGN_ID:雪花算法生成Long类型的全局唯一id,这是默认的ID策略

3、@TableField

该注解用于标记实体类中的非主键字段,它告诉 MyBatis-Plus 如何映射实体类字段到数据库表字段。如果你的实体类字段名遵循驼峰命名规则,并且与数据库表字段名一致,你可以省略这个注解。

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname") // 映射到数据库字段 "nickname"
    private String name;
    private Integer age;
    private String email;
    @TableField("isMarried")
    private Boolean isMarried;
    @TableField(value = "`order`") // 数据库字段名为 order,使用反引号转义
    private String order;
}

一般情况下我们并不需要给字段添加@TableField注解,一些特殊情况除外:

  • 成员变量名与数据库字段名不一致
  • 成员变量是以isXXX命名,按照JavaBean的规范,MybatisPlus识别字段时会把is去除,这就导致与数据库不符。
  • 成员变量名与数据库一致,但是与数据库的关键字冲突。使用@TableField注解给字段名添加转义字符:``
    支持的其它属性如下:
    在这里插入图片描述

condition (需要有MP的相关知识,初学先跳过)
在执行实体查询(EntityQuery)时,指定字段的条件表达式。这允许你自定义字段在 WHERE 子句中的比较方式。如果该项有值则按设置的值为准,无值则默认为全局的 %s=#{%s} 为准。

示例说明
假设我们有一个实体类 User,它有 id、name 和 age 三个字段。我们想要查询所有年龄大于 18 岁的用户,我们可以使用 QueryWrapper 来构建这个查询,直接传递 User 实体类实例:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.SqlCondition;

// 实体类定义
@TableName("sys_user")
public class User {
    @TableId
    private Long id;

    private String name;

    @TableField(condition = "%s > #{%s}") // 自定义 age 字段的条件表达式
    private Integer age;

    private String email;
}

// 使用 EntityQuery 构建查询
public List<User> findUserAgeOver18() {
    // 创建 User 实例,用于设置查询条件
    User queryEntity = new User();
    queryEntity.setAge(18); // 设置 age 字段的值

    // 创建 QueryWrapper 实例,并传递 User 实例
    QueryWrapper<User> queryWrapper = new QueryWrapper<>(queryEntity);

    // 执行查询
    List<User> userList = userMapper.selectList(queryWrapper);

    return userList;
}

在这个例子中,我们通过 @TableField(condition = “%s > #{%s}”) 注解为 age 字段设置了自定义的条件表达式。当构建查询时,我们创建了一个 User 实例,并设置了 age 字段的值为 18。然后,我们使用这个实例来创建 QueryWrapper,MyBatis-Plus 会根据实体类上的注解自动生成相应的 SQL 查询条件。

执行 findUserAgeOver18 方法时,MyBatis-Plus 会生成类似以下的 SQL 语句:

SELECT * FROM sys_user WHERE age > 18; 

通过这种方式,condition 属性允许我们自定义字段在查询时的行为,使得查询更加灵活和符合特定需求,同时避免了手动编写 SQL 片段的繁琐。

fill
字段自动填充策略。该属性用于指定在执行数据库操作(如插入、更新)时,如何自动填充字段的值。通过使用 FieldFill 枚举,可以灵活地控制字段的填充行为。

注意:此功能需要配合自动填充字段功能一起使用。(后续会介绍)
示例说明

假设有一个 User 实体类,其中包含 createTime 和 updateTime 字段,我们希望在创建用户时自动填充创建时间,在更新用户信息时自动填充更新时间。

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.time.LocalDateTime;

@TableName("user")
public class User {
    // 其他字段...

    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    @TableField(fill = FieldFill.UPDATE)
    private LocalDateTime updateTime;

    // 构造函数、getter 和 setter...
}

在这个示例中,createTime 字段会在插入操作时自动填充当前时间,而 updateTime 字段会在更新操作时自动填充当前时间。这样,我们就不需要在每次数据库操作时手动设置这些时间字段的值了。

请注意,为了使自动填充功能正常工作,需要在 MyBatis-Plus 的配置中设置相应的自动填充处理器,并且确保在实体类对应的 Mapper 接口中定义了相应的插入和更新方法。(完整流程后续介绍)

4、@Version

该注解用于标记实体类中的字段作为乐观锁版本号字段。乐观锁是一种并发控制机制,它假设多个事务可以同时进行而不会互相干扰,只在提交事务时检查是否有冲突。通过在实体类中使用@Version注解,MyBatis-Plus 会在更新操作时自动检查版本号,确保在更新过程中数据没有被其他事务修改。

@TableName("sys_user")   
public class User {   
    @TableId   
    private Long id;   
    @TableField("nickname") // 映射到数据库字段 "nickname"   
    private String name;   
    private Integer age;   
    private String email;   
    @Version // 标记为乐观锁版本号字段   
    private Integer version;   
}

在上面的示例中,version字段被标记为乐观锁版本号。当执行更新操作时,MyBatis-Plus 会检查该字段的值是否与数据库中的值一致。如果不一致,说明在读取数据后有其他事务修改了数据,此时会抛出乐观锁异常,提示开发者进行相应的处理。

使用@Version注解可以有效地防止并发更新时出现的数据不一致问题,提高系统的并发性能和数据完整性。开发者无需手动编写版本号检查的代码,MyBatis-Plus 会自动处理这一过程。

5、@EnumValue

该注解用于标记枚举类中的字段,指定在数据库中存储的枚举值。当实体类中的某个字段是枚举类型时,使用@EnumValue注解可以告诉MyBatis-Plus在数据库中存储枚举值的哪个属性。

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname") // 映射到数据库字段 "nickname"
    private String name;
    private Integer age;
    private String email;
    private Gender gender; // 假设 Gender 是一个枚举类型
}

public enum Gender {
    MALE("M", "男"),
    FEMALE("F", "女");

    private String code;
    private String description;

    Gender(String code, String description) {
        this.code = code;
        this.description = description;
    }

    @EnumValue // 指定存储到数据库的枚举值为 code
    public String getCode() {
        return code;
    }
}

在上面的示例中,Gender枚举类中的code字段被标记为@EnumValue,这意味着在数据库中存储User实体类的gender字段时,将存储Gender枚举的code值,而不是枚举常量本身。

使用@EnumValue注解可以灵活地控制枚举类型在数据库中的存储方式,使得数据库中的数据更加紧凑和易于处理。同时,它也简化了从数据库读取枚举值时的转换过程,因为MyBatis-Plus会自动根据@EnumValue注解的配置将数据库中的值转换为对应的枚举实例。

6、@TableLogic

该注解用于标记实体类中的字段作为逻辑删除字段。逻辑删除是一种数据管理策略,它不是真正地从数据库中删除记录,而是在记录中标记该记录为已删除状态。通过使用@TableLogic注解,MyBatis-Plus 可以在查询、更新和删除操作中自动处理逻辑删除字段的值。

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname") // 映射到数据库字段 "nickname"
    private String name;
    private Integer age;
    private String email;
    @TableLogic(value = "0", delval = "1") // 逻辑删除字段
    private Integer deleted;
}

在上面的示例中,deleted字段被标记为逻辑删除字段。@TableLogic注解的value属性指定了逻辑未删除的值(在这个例子中是0),而delval属性指定了逻辑删除的值(在这个例子中是1)。

当执行查询操作时,MyBatis-Plus 会自动过滤掉标记为逻辑删除的记录,只返回未删除的记录。在执行更新操作时,如果更新操作会导致逻辑删除字段的值变为逻辑删除值,MyBatis-Plus 会自动将该记录标记为已删除。在执行删除操作时,MyBatis-Plus 会自动将逻辑删除字段的值更新为逻辑删除值,而不是物理删除记录。

使用@TableLogic注解可以实现数据的逻辑删除,有助于维护数据的完整性和可追溯性,同时避免了物理删除操作可能带来的数据丢失风险。开发者无需手动编写逻辑删除的代码,MyBatis-Plus 会自动处理这一过程。

7、@OrderBy

该注解用于指定实体类中的字段在执行查询操作时的默认排序方式。通过在实体类字段上使用@OrderBy注解,可以确保在执行查询时,如果没有显式指定排序条件,MyBatis-Plus 将按照注解中定义的排序规则返回结果。

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname") // 映射到数据库字段 "nickname"
    private String name;
    @OrderBy(asc = false, sort = 10) // 指定默认排序为倒序,优先级为10
    private Integer age;
    private String email;
}

在上面的示例中,age字段被标记为@OrderBy,并设置了asc属性为false,表示默认排序为倒序(降序),sort属性设置为10,表示该排序规则的优先级。

@OrderBy注解的asc属性用于指定排序是否为升序,如果设置为true,则表示升序排序;如果设置为false,则表示降序排序。sort属性用于指定排序规则的优先级,数字越小,优先级越高,即越先被应用。

需要注意的是,@OrderBy注解的排序规则优先级低于在查询时通过Wrapper条件查询对象显式指定的排序条件。如果在Wrapper中指定了排序条件,那么@OrderBy注解中定义的默认排序将被覆盖。

使用@OrderBy注解可以简化代码,避免在每次查询时都显式指定排序条件,同时提供了一种默认的排序方式,有助于提高代码的可读性和维护性。

最后几个注解来自官网介绍,学起来也很简单,大家一定要看着代码进行理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值