05.类型增强

类型增强

字段类型处理器

类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 PreparedStatement 设置参数值和从 ResultSet 或 CallableStatement 中取出一个值。

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {
    private Long id;

    ...

    /**
     * 注意!! 必须开启映射注解
     *
     * @TableName(autoResultMap = true)
     *
     * 以下两种类型处理器,二选一 也可以同时存在
     *
     * 注意!!选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    // @TableField(typeHandler = FastjsonTypeHandler.class)
    private OtherInfo otherInfo;

}

该注解对应了 XML 中写法为:

<result column="other_info" jdbcType="VARCHAR" property="otherInfo" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />

案例

首先,自定义类型处理器:

public class TestTypeHandler extends BaseTypeHandler<String> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, "TestTypeHandler set {" + parameter + "}");
    }

    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String string = rs.getString(columnName);
        return "TestTypeHandler(rs columnName) get {" + string + "}";
    }

    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String string = rs.getString(columnIndex);
        return "TestTypeHandler(rs columnIndex) get {" + string + "}";
    }

    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String string = cs.getString(columnIndex);
        return "TestTypeHandler(cs columnIndex) get {" + string + "}";
    }
}

然后在需要使用该类型的地方添加注解:

@TableField(typeHandler = TestTypeHandler.class)
private String email;

主键

自 3.3.0 开始,默认使用雪花算法+UUID(不含中划线):

方法 主键生成策略 主键类型 说明
nextId ASSIGN_ID,ID_WORKER,ID_WORKER_STR Long,Integer,String 支持自动转换为 String 类型,但数值类型不支持自动转换,需精准匹配,例如返回 Long,实体主键就不支持定义为 Integer
nextUUID ASSIGN_UUID,UUID String 默认不含中划线的 UUID 生成
  • 方式一:声明为 Bean 供 Spring 扫描注入
@Component
public class CustomIdGenerator implements IdentifierGenerator {
    @Override
    public Long nextId(Object entity) {
      	//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
      	String bizKey = entity.getClass().getName();
        //根据bizKey调用分布式ID生成
        long id = ....;
      	//返回生成的id值即可.
        return id;
    }
}
  • 方式二:使用配置类
@Bean
public IdentifierGenerator idGenerator() {
    return new CustomIdGenerator();
}
  • 方式三:通过 MybatisPlusPropertiesCustomizer 自定义
@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
    return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}

通用枚举

自 3.1.0 开始,如果你无需使用原生枚举,可配置默认枚举来省略扫描通用枚举配置默认枚举配置。

声明通用枚举属性

// 方式一:使用 @EnumValue 注解枚举属性
public enum GradeEnum {

    PRIMARY(1, "小学"),  SECONDORY(2, "中学"),  HIGH(3, "高中");

    GradeEnum(int code, String descp) {
        this.code = code;
        this.descp = descp;
    }

    @EnumValue//标记数据库存的值是code
    private final int code;
    //。。。
}

// 方式二:枚举属性,实现 IEnum 接口如下:
public enum AgeEnum implements IEnum<Integer> {
    ONE(1, "一岁"),
    TWO(2, "二岁"),
    THREE(3, "三岁");

    private int value;
    private String desc;

    @Override
    public Integer getValue() {
        return this.value;
    }
}

// 实体属性使用枚举类型
public class User {
    /**
     * 名字
     * 数据库字段: name varchar(20)
     */
    private String name;

    /**
     * 年龄,IEnum接口的枚举处理
     * 数据库字段:age INT(3)
     */
    private AgeEnum age;


    /**
     * 年级,原生枚举(带{@link com.baomidou.mybatisplus.annotation.EnumValue}):
     * 数据库字段:grade INT(2)
     */
    private GradeEnum grade;
}

配置扫描通用枚举

mybatis-plus:
    # 支持统配符 * 或者 ; 分割
    typeEnumsPackage: com.baomidou.springboot.entity.enums
  ....
  • Jackson
// 重写toString方法
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer(){
    return builder -> builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
}

// 注解处理
public enum GradeEnum {

    PRIMARY(1, "小学"),  SECONDORY(2, "中学"),  HIGH(3, "高中");

    GradeEnum(int code, String descp) {
        this.code = code;
        this.descp = descp;
    }

    @EnumValue
  	@JsonValue	//标记响应json值
    private final int code;
}
  • Fastjson
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteEnumUsingToString);

@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
private UserStatus status;
上一页
下一页