从请求到入库都使用枚举

核心的目标是,用户传递的某个字段的值,在@RequestBody转换后,自动转换成枚举,因为枚举是全局的,所以可以直接赋值给entity的相应字段,然后调用mapper的方法进行入库。

这个过程核心需求解决的问题如下:

  1. 用户提交数据时,需要将用户提交的值转换成一个枚举
  2. controller方法是,需要将entity中的枚举的值返回回去
  3. entity写入到库中时,需要完成枚举到值的转换
  4. 从库中读取数据到entity时,自动完成值到枚举的转换

提交、查询阶段

request类如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

@Data
public class CreateDomainModelRequest {

    /**
     * 领域ID
     */
    private String domainId;

    /**
     * 模型名
     */
    private String modelName;

    /**
     * 类型
     * @see com.sdstc.dyf.meta.common.constant.enums.ModelType#value
     */
    @JSONField(serializeUsing = EnumCodec.class, deserializeUsing = EnumCodec.class)
    private ModelType modelType;

    /**
     * 组织ID
     */
    private String orgId;

    /**
     * 注意事项
     */
    private String note;

}

其中ModelType枚举的代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

package com.sdstc.dyf.meta.common.constant.enums;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.AccessLevel;

/**
 * 类型
 */
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public enum ModelType {


    /**
     * 系统
     */
    SYSTEM("1"),

    /**
     * 自定义
     */
    CUSTOM("3"),

    ;

    @Getter
    private String value;

    public static ModelType convert(String inputValue) {
        for (ModelType enumItem : ModelType.values()) {
            if (enumItem.getValue().equals(inputValue)) {
                return enumItem;
            }
        }
        throw new RuntimeException("Enum Transfer Wrong.");
    }


}

入库、出库阶段

代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@TableName(value = "t_dyf_domain_model", autoResultMap = true)
public class DomainModelPo extends BasePo {

    /**
     * 领域ID
     */
    private String domainId;

    /**
     * 模型名
     */
    private String modelName;

    /**
     * 类型
     */
   @TableField(typeHandler = ModelTypeTypeHandler.class)
   private ModelType modelType;

    /**
     * 组织ID
     */
    private String orgId;

    /**
     * 注意事项
     */
    private String note;

}

其中ModelTypeTypeHandler.java的代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16

@Slf4j
@MappedTypes({Object.class})
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ModelTypeTypeHandler extends AbstractEnumTypeHandler<ModelType> {
    @Override
    protected ModelType parseValue(String inputParam) {
        return ModelType.convert(inputParam);
    }

    @Override
    protected String toValue(ModelType isModelRequired) {
        return isModelRequired.getValue();
    }
}

其中AbstractEnumTypeHandler.java的代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

public abstract class AbstractEnumTypeHandler<T> extends BaseTypeHandler<T> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
        ps.setObject(i, toValue(parameter));
    }

    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        final Object inputParam = rs.getObject(columnName);
        return parseValue(String.valueOf(inputParam));
    }

    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        final Object inputParam = rs.getObject(columnIndex);
        return parseValue(String.valueOf(inputParam));
    }

    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        final Object inputParam = cs.getObject(columnIndex);
        return parseValue(String.valueOf(inputParam));
    }

    protected abstract T parseValue(String inputParam);

    protected abstract String toValue(T enumObject);
}

参考资料

  1. MybatisPlus中@TableField注解的使用

  2. https://blog.csdn.net/intersting/article/details/93768803

  3. 深入解析Spring使用枚举接收参数和返回值机制并提供自定义最佳实践

    这部分内容包含了一些知识,但是我这次解决问题并没有使用到这些知识。

  4. 自定义fastjson对枚举类型的序列化及反序列化过程

    有参考该份文档。