Springboot3 Mybatis-plus 3.5.9

发布于:2024-12-18 ⋅ 阅读:(138) ⋅ 点赞:(0)

1. Mybatis-plus

官网:链接

1. 依赖

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
  <version>3.5.9</version>
</dependency>

2. 注解配置表名、字段名

一般情况下,数据库映射为实体类对应关系

  1. 数据库表与实体类类名:下划线转为驼峰
  2. 实体类中的id字段对应数据库中的主键字段id
  3. 表中列名与实体类属性名:下划线转驼峰

如不满足以上条件,需在实体类中使用注解

  1. 表名注解:@TableName:用来指定表名
  2. 指定主键:@TableId 指定表中的主键
  3. 实体类属性注解:@TableField 指定表中的字段信息
// 指定该实体类对应的表名是t_vip
@TableName("`t_vip`")
public class Vip {
    // 指定该属性为主键,且在数据表中的列名为id,且自增
    @TableId(value = "id", type = IdType.AUTO)
    private Long vid;
    // 指定该属性对应表中的username列
    @TableField(value = "username")
    private String name;
    // 数据表中不存在该属性对应的列
    @TableField(exist = false)
    private String birthday;
}

@TableId:常见类型

  • 主键最好指定类型,默认是type = IdType.ASSIGN_ID
    @TableId(type = IdType.AUTO)  // 主键自增,数据库自动生成
    @TableId(type = IdType.INPUT) // 通过set方法自行输入,例如uuid作为主键,需要手动赋值
    @TableId( type = IdType.ASSIGN_ID)  // 通过接口生成主键,由mybatis-plus自动生成

@TableField:常见场景

  1. 实体类属性与数据库表中字段不一致,
  	// 属性是name,表中是username
    @TableField("username")
    private String name;
  1. 表中以is开头并且是boolean值
// 表中字段名:is_ban,映射的属性名为ban
   @TableField("is_ban")
    private Boolean name;
  1. 属性名与数据库的关键字一致
// order在数据库中是关键字,注意使用了 ``
   @TableField("`order`")
    private String order;
  1. 属性并不属于数据库表中的字段
    // 数据表中不存在该属性对应的列
    @TableField(exist = false)
    private String birthday;

3. yml中的配置

官方:链接

  • 很多默认配置已经足够了
mybatis-plus:
  type-aliases-package: org.example.learn.domain  # 实体类包
  global-config:
    db-config:
      id-type: auto # id生成策略:自增长
      logic-delete-field: deleted # 表中的逻辑删除字段名
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
    banner: false # 是否在控制台打印 MyBatis-Plus 的 LOGO
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler  # 枚举类型处理器

4. mapper和service的用法

  1. mapper:继承BaseMapper接口
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.learn.bean.User;	// 实体类

@Mapper
public interface UserMapper extends BaseMapper<User> {
}
  1. service:继承IService接口
import com.baomidou.mybatisplus.extension.service.IService;
import org.example.learn.bean.User;	// 实体类

public interface UserService extends IService<User> {
}
  1. service的实现类seviceImpl:继承ServiceImpl

ServiceImpl:两个泛型

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.learn.bean.User;
import org.example.learn.dao.UserMapper;
import org.example.learn.service.UserService;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
}

2. 使用工具生成mapper和service

在这里插入图片描述

在这里插入图片描述

3. 逻辑删除

  • 在实际应用中很多数据是不能删除的,比如:订单信息,mybatis-plus提供了逻辑删除
  • 逻辑删除:使用数据表中的某一个列,通过列的值表示该数据是否被删除

1. 需要在yml中配置

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 表中的逻辑删除字段名
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

2. 代码

代码还是使用正常的删除和查询操作,mybaits-plus在删除时实际使用的是updata操作,查询时总是会把标志位作为条件带入

  1. 使用remove方法删除时,mybatis-plus使用了updata方法更新了逻辑删除的列
    addressService.removeById(59L);
    /*
    * ==>  Preparing: UPDATE address SET deleted=1 WHERE id=? AND deleted=0
    *  ==> Parameters: 59(Long)
    *  <==    Updates: 0
    * */
  1. 查询时也会自动添加逻辑删除标志位为未删除的条件
    Address address = addressService.getById(59L);
    /*
    * ==>  Preparing: SELECT id,user_id,province,city,town,mobile,street,contact,is_default,notes,deleted FROM address WHERE id=? AND deleted=0
    * ==> Parameters: 59(Long)
    * <==      Total: 0
    * */

4. json类型映射对象

在数据表中类型格式为json,在查询、新增、更新等操作时,此数据转为对象形式

在这里插入图片描述

1. 定义json类型字段内容对应的类

{"age": 20, "intro": "佛系青年", "gender": "male"}

@Data
public class UserInfo {
  private Integer age;
  private String intro;
  private String gender;

}

2. 在数据表对应的类属性和类上加注解

  • 类上注解:@TableName(autoResultMap = true)
  • 属性注解:@TableField(typeHandler = JacksonTypeHandler.class)
@Data
//@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User implements Serializable {
    /**
     * 详细信息
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    private UserInfo info;
}

3. 在查询后返回的结果就是对象形式

在这里插入图片描述

5. 自动映射枚举

经常使用数字或布尔值代表一种状态,每次查询或新增时都需要对照状态表来解释状态码。
例如:

  //  private Boolean gender; // 男/女
    private Integer status;	// 使用状态(1正常 2冻结)

1. 配置yml

mybatis-plus:
  configuration:
    default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

2. 创建枚举类映射

@Getter
public enum UserStatus {
    NORMAL(1, "正常"),
    FREEZE(2, "冻结");

    @EnumValue // 在数据库存/取的值是code的属性值
    private final Integer code;
    @JsonValue  // 在序列化时返回的JSON中显示的属性值
    private final String desc;

    UserStatus(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

}

3. 修改数据表对应的实体类中该属性的类型

    /**
     * 使用状态(1正常 2冻结)
     */
    private UserStatus status;

4. 使用

    // 1. 查询id是否存在
    User user = this.getById(id);
    if (user == null || user.getStatus() == UserStatus.FREEZE) {
      throw new RuntimeException("用户不存在或已经被禁用");
    }

6. 创建时间和修改时间自动填充

  • 在创建和修改是自动填写时间
// 实体类中的属性,启用自动填充
    /**
     * 创建时间
     */
     // FieldFill.INSERT:只有在insert操作时才会使用自定义的处理器
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
     // FieldFill.INSERT_UPDATE :插入和更新操作都会使用自定义的处理器
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime
  • 定义处理器
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
  @Override
  // insert操作时会同时更新createTime 和 updateTime 
  public void insertFill(MetaObject metaObject) {
    // 检查create_time字段是否为null,如果是,设置为当前时间
    LocalDateTime createTime = (LocalDateTime) getFieldValByName("createTime", metaObject);
    if (createTime == null) {
      setFieldValByName("createTime", LocalDateTime.now(), metaObject);
    }
    LocalDateTime updateTime = (LocalDateTime) getFieldValByName("updateTime", metaObject);
    if ( updateTime == null) {
      setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
    }
  }

  @Override
  public void updateFill(MetaObject metaObject) {
    // 如果有更新时间字段,如update_time,可以在这里处理填充逻辑
     LocalDateTime updateTime = (LocalDateTime) getFieldValByName("updateTime", metaObject);
     if (updateTime == null) {
         setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
     }
  }
}

pom中所有的依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
        <!--swagger-->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
            <version>4.1.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>