MyBatis通过枚举实现字段自动转义

Yohann-study

MyBatis通过枚举实现字段自动转义

定义接口规范

public interface TranslationEnum {
    /**
     * 获取枚举只
     *
     * @param code 枚举编号
     * @return 枚举值
     */
    Object getValue(Object code);
}

定义运行时注解

/**
 * 开启字段转化功能
 *
 * @author Yeung Wah
 * @since 2021/9/17
 */
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EnableConvert {
}

/**
 * 枚举转化信息
 *
 * @author Yeung Wah
 * @since 2021/9/17
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ConvertEnum {
    /**
     * 枚举类
     *
     * @return 枚举类字节码信息
     */
    Class<? extends TranslationEnum> clazz();

    /**
     * 需要翻译的字段
     *
     * @return 字段名
     */
    String codeField();
}

POJO及枚举配置

@EnableConvert
public class TestEntity {
    @ConvertEnum(clazz = TestEnum.class, codeField = "age")
    private String name;
    private Integer age;
}

@Getter
public enum TestEnum implements TranslationEnum{
    /**
     * test enums
     */
    TEST_1(1, "test1"),
    TEST_2(2, "test2"),
    ;

    private Integer code;
    private String value;

    TestEnum(Integer code, String value) {
        this.code = code;
        this.value = value;
    }

    /**
     * 静态缓存枚举加速
     */
    private static final Map<Object, String> VALUE_MAP = new HashMap<>(TestEnum.values().length * 4 / 3);

    static {
        for (TestEnum value : TestEnum.values()) {
            VALUE_MAP.put(value.code, value.value);
        }
    }

    @Override
    public Object getValue(Object code) {
        return VALUE_MAP.get(code);
    }
}

工具类具体实现

@Slf4j
public class ConvertUtils {

    private ConvertUtils() {
    }

    public static <T> void convertEnums(T t) {
        //对象为空则直接结束
        if (Objects.isNull(t)) {
            return;
        }

        for (Class<?> clazz = t.getClass(); !clazz.equals(Object.class); clazz = clazz.getSuperclass()) {
            //开启翻译
            if (clazz.isAnnotationPresent(EnableConvert.class)) {
                Field[] fields = clazz.getDeclaredFields();
                Field.setAccessible(fields, true);

                for (Field field : fields) {
                    //枚举翻译
                    ConvertEnum convertEnum = field.getAnnotation(ConvertEnum.class);
                    if (Objects.nonNull(convertEnum)) {
                        //获取注解信息
                        Class<? extends TranslationEnum> enumClazz = convertEnum.clazz();

                        try {
                            //获取需要翻译的字段值
                            Field codeField = clazz.getDeclaredField(convertEnum.codeField());
                            codeField.setAccessible(true);
                            Object code = codeField.get(t);

                            //获取枚举实例对象 獲取映射字段
                            if (!enumClazz.isEnum()) {
                                throw new RuntimeException(enumClazz.getName() + "非枚举类型");
                            } else if (enumClazz.getEnumConstants().length == 0) {
                                throw new RuntimeException(enumClazz.getName() + "无实例");
                            }
                            TranslationEnum translationEnum = enumClazz.getEnumConstants()[0];
                            if (Objects.nonNull(translationEnum)) {
                                Object value = translationEnum.getValue(code);
                                field.set(t, value);
                            }
                        } catch (Exception e) {
                            LogUtils.debug("convert exception:" + e.getMessage(), e);
                        }
                    }
                }
            }
        }
    }

    public static <T> void convertEnums(List<T> list) {
        //集合为空则直接结束
        if (list.isEmpty()) {
            return;
        }

        list.forEach(ConvertUtils::convertEnums);
    }

}

mybatis拦截器转义结果集

@Configuration
public class MyBatisTranslateConfig {

    @Bean
    public TranslateInterceptor getInterceptor() {
        return new TranslateInterceptor();
    }

    /**
     * 自定义拦截器
     */
    @Intercepts({
            @Signature(
                    // 只拦截查询
                    method = "query",
                    type = Executor.class,
                    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
            @Signature(
                    //处理结果集
                    type = ResultSetHandler.class,
                    method = "handleResultSets",
                    args = Statement.class)
    })
    private static class TranslateInterceptor implements Interceptor {
        @Override
        @SuppressWarnings("unchecked")
        public Object intercept(Invocation invocation) throws Throwable {
            List<Object> objects = (List<Object>) invocation.proceed();
            ConvertUtils.convertEnums(objects);
            return objects;
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis-Plus 是一个优秀的 MyBatis 增强工具,在实际开发中我们经常需要使用枚举类型来表示一些常量,如订单状态、性别等。而 MyBatis-Plus 对枚举类型的处理也非常方便,下面我来介绍一下如何使用 MyBatis-Plus 枚举字段映射。 1. 定义枚举类型 首先我们需要定义一个枚举类型,如下所示: ```java public enum StatusEnum { ENABLE(1, "启用"), DISABLE(0, "禁用"); private Integer value; private String desc; StatusEnum(Integer value, String desc) { this.value = value; this.desc = desc; } public Integer getValue() { return value; } public String getDesc() { return desc; } } ``` 2. 实体类中使用枚举类型 在实体类中使用枚举类型,如下所示: ```java public class User { private Long id; private String name; private StatusEnum status; // getter 和 setter 略 } ``` 3. 数据库表中使用枚举字段 在数据库表中使用枚举字段,如下所示: ```sql CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `status` tinyint(4) NOT NULL COMMENT '状态:1=启用,0=禁用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表'; ``` 其中,`status` 字段类型为 `tinyint`,用于存储枚举类型的值。 4. 枚举字段映射 在 MyBatis-Plus 中,我们可以使用 `@EnumValue` 和 `@EnumValue` 注解来进行枚举字段映射。具体使用方法如下: ```java public class User { private Long id; private String name; @EnumValue private StatusEnum status; // getter 和 setter 略 } ``` 在 `status` 字段上添加 `@EnumValue` 注解,表示该字段枚举类型的值。 ```java public interface UserMapper extends BaseMapper<User> { } ``` 在 Mapper 中继承 `BaseMapper` 接口即可,无需做任何其他配置。 5. 查询操作 在查询操作时,MyBatis-Plus 会自动将数据库中存储的枚举类型的值映射为实体类中的枚举类型。例如: ```java User user = userMapper.selectById(1L); System.out.println(user.getStatus()); // 输出:ENABLE ``` 在上述代码中,MyBatis-Plus 会自动将数据库中的 `status` 字段的值 `1` 映射为实体类中的 `StatusEnum.ENABLE`。 6. 插入和更新操作 在插入和更新操作时,MyBatis-Plus 会自动将实体类中的枚举类型映射为数据库中的枚举类型的值。例如: ```java User user = new User(); user.setName("张三"); user.setStatus(StatusEnum.ENABLE); userMapper.insert(user); ``` 在上述代码中,MyBatis-Plus 会自动将实体类中的 `StatusEnum.ENABLE` 映射为数据库中的 `status` 字段的值 `1`。 综上所述,使用 MyBatis-Plus 枚举字段映射非常方便,只需要在实体类中添加 `@EnumValue` 注解即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值