我的编程空间,编程开发者的网络收藏夹
学习永远不晚

orika 中解决UnmappableEnum抛错的错误

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

orika 中解决UnmappableEnum抛错的错误

在使用orika 做bean工具的时候,如果beanA的某属性类型为Integer ,要转换为beanB的同名属性的类型是一个enum,这个时候,就会出现如下报错:

Error occurred: ma.glasnost.orika.MappingException: Encountered mapping of enum to object (or vise-versa); sourceType=Integer, destinationType=GenderEnum

Caused by: ma.glasnost.orika.MappingException: Encountered mapping of enum to object (or vise-versa); sourceType=Integer, destinationType=GenderEnum
at ma.glasnost.orika.impl.generator.specification.UnmappableEnum.generateMappingCode(UnmappableEnum.java:41)
at ma.glasnost.orika.impl.generator.SourceCodeContext.mapFields(SourceCodeContext.java:759)

我们找到这个UnmappableEnum类,可以看到此处的抛错代码

public class UnmappableEnum extends AbstractSpecification {

    public boolean appliesTo(FieldMap fieldMap) {
        return fieldMap.getBType().isEnum() && !fieldMap.getAType().isEnum() && !fieldMap.getAType().isString();
    }

    public String generateMappingCode(FieldMap fieldMap, VariableRef source, VariableRef destination, SourceCodeContext code) {
        throw new MappingException("Encountered mapping of enum to object (or vise-versa); sourceType="+
                source.type() + ", destinationType=" + destination.type());
    }

}

下面我们顺藤摸瓜,找到默认的代码生成策略类DefaultCodeGenerationStrategy,可以看到这段代码
public DefaultCodeGenerationStrategy() {

    this.specifications = new CopyOnWriteArrayList<Specification>(
            Arrays.asList(
                    new ConvertArrayOrCollectionToArray(),
                    new ConvertArrayOrCollectionToCollection(),
                    new Convert(),
                    new CopyByReference(),
                    new ApplyRegisteredMapper(),
                    new EnumToEnum(),
                    new StringToEnum(),
                    new UnmappableEnum(),
                    new ArrayOrCollectionToArray(),
                    new ArrayOrCollectionToCollection(),
                    new MapToMap(),
                    new MapToArray(),
                    new MapToCollection(),
                    new ArrayOrCollectionToMap(),
                    new StringToStringConvertible(),
                    new AnyTypeToString(),
                    new MultiOccurrenceElementToObject(),
                    new ObjectToMultiOccurrenceElement(),
                    new PrimitiveAndObject(),
                    new ObjectToObject()));

    this.aggregateSpecifications = new CopyOnWriteArrayList<AggregateSpecification>(
            Arrays.asList(new MultiOccurrenceToMultiOccurrence()));

}

由代码逻辑可以看到,默认策略下,枚举只支持Enum和String 两种类型的转换,并不支持其他类型转枚举的。一般情况下,我们数据库记录的应该是枚举的name值,但是,如果遇到某些历史遗留问题 ,暂时不能改变,怎么办?只能让orika支持枚举转换。

我们来试试,在不改动orika的情况下,怎么通过配置,让其支持Integer转Enum。
环境:group: ‘com.gitlab.haynes’, name: ‘orika-spring-boot-starter’, version: ‘1.26.0’

UserA

@Data
@With
@AllArgsConstructor
@NoArgsConstructor
public class UserA {
    private String name;
    private Integer age;
    private Integer gender;
}

UserB
@Data
@With
@AllArgsConstructor
@NoArgsConstructor
public class UserB {
    private String name;
    private Integer age;
    private GenderEnum gender;
}

GenderEnum
@AllArgsConstructor
public enum GenderEnum {
    MALE(1,"男"),
    FEMALE(2,"女");

    @Getter
    @Setter
    private Integer value;

    @Setter
    @Getter
    private String label;
}

我们在UserA中的gender属性是Integer的,UserB中的gender属性是Enum的。直接转换,这里会报开头我们说的错误。
@Test
public void t1(){
    UserA userA = new UserA().withName("test").withAge(10).withGender(1);
    UserB userB = mapperFacade.map(userA, UserB.class);
    System.out.println(userB);
}

我们来解决这个问题 1.通过自定义mapper的方式 在GenderEnum添加一个静态函数,通过value可以获得对应的enum
@AllArgsConstructor
public enum GenderEnum {
    MALE(1,"男"),
    FEMALE(2,"女");

    @Getter
    @Setter
    private Integer value;

    @Setter
    @Getter
    private String label;

    public static GenderEnum of(Integer value){
        if(Objects.isNull(value)){
            return null;
        }
        for (GenderEnum item: GenderEnum.values()){
            if(Objects.equals(item.getValue(),value)){
                return item;
            }
        }
        return null;
    }
}


写一个configurer自己,默认情况下不去给gender属性复制,后面自己给他手动赋值。
@Component
public class UserMapping implements OrikaMapperFactoryConfigurer {
    @Override public void configure(MapperFactory mapperFactory) {
        mapperFactory.classMap(UserA.class,UserB.class).exclude("gender").byDefault().customize(
                new CustomMapper<UserA, UserB>() {
                    @Override public void mapAtoB(UserA userA, UserB userB, MappingContext context) {
                        userB.setGender(GenderEnum.of(userA.getGender()));
                    }
                }).register();
    }
}

测试结果如下

UserB(name=test, age=10, gender=MALE)


2.注册全局的converter 如果GenderEnum会在很多地方使用的话,在User对象转换中指定,就不太通用了。我们可以注册成为全局的Converter。
@Component
public class GenderConverter extends CustomConverter<Integer,GenderEnum> {
    @Override public GenderEnum convert(Integer source, Type<? extends GenderEnum> destinationType,
            MappingContext mappingContext) {
        return GenderEnum.of(source);
    }
}
@RequiredArgsConstructor
@Component
public class GlobalMapperFactoryConfigurer implements OrikaMapperFactoryConfigurer {

    private final List<Converter<?,?>> converters;

    @Override public void configure(MapperFactory orikaMapperFactory) {
        ConverterFactory converterFactory = orikaMapperFactory.getConverterFactory();
        if(!CollectionUtils.isEmpty(converters)){
            converters.forEach(converterFactory::registerConverter);
        }
    }
}

运行测试代码:

UserB(name=test, age=10, gender=MALE)

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

orika 中解决UnmappableEnum抛错的错误

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Promise抛出错误解决基础示例详解

这篇文章主要为大家介绍了Promise抛出错误解决基础示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-12-15

pytest中Fixture errors抛错怎么解决

本篇内容主要讲解“pytest中Fixture errors抛错怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“pytest中Fixture errors抛错怎么解决”吧!首先,在pyte
2023-06-30

Vue使用v-for语句时抛出错误怎么解决

本篇内容主要讲解“Vue使用v-for语句时抛出错误怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Vue使用v-for语句时抛出错误怎么解决”吧!Vue 中使用v-for语句抛出错误的解
2023-07-04

解决Python中JSONDecodeError:Expectingvalue:line1column1(char0)错误

这篇文章主要介绍了解决Python中JSONDecodeError:Expectingvalue:line1column1(char0)错误问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-22

MySQL中的套接字错误解决

MySQL套接字错误通常是连接问题导致的。常见错误包括:连接终止、连接超时、无法解析主机名、服务器断开连接、无法建立连接和网络中断。解决方案包括检查网络连接、服务器状态、主机名解析、重新启动服务器、调整端口设置和启用重试机制。最佳实践是使用稳定网络、持久连接、调整超时值、启用重试和定期维护服务器。
MySQL中的套接字错误解决
2024-04-02

Python中ModuleNotFoundError错误的问题解决

本文主要介绍了Python中ModuleNotFoundError错误的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-02-10

python中的unicode错误怎么解决

在Python中,Unicode错误通常是由于字符串编码不匹配或无效的Unicode字符引起的。解决Unicode错误的方法取决于具体的错误类型和场景,以下是一些常见的解决方法:1. 使用正确的编码:确保在处理字符串时使用正确的编码。可以使
2023-08-25

php中curl56错误的解决方法

这篇文章给大家分享的是有关php中curl56错误的解决方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。php curl 56错误的解决方法是设置“curl_setopt($c, CURLOPT_SSL_VER
2023-06-20

php中readfile错误的解决方法

这篇文章给大家分享的是有关php中readfile错误的解决方法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。php有什么用php是一个嵌套的缩写名称,是英文超级文本预处理语言,它的语法混合了C、Java、Per
2023-06-15

asp中vbscript.encode错误怎么解决

您好!在ASP中,vbscript.encode是用于对字符串进行编码的函数。如果您遇到vbscript.encode的错误,可能是由于以下原因之一:您的ASP页面中没有正确声明vbscript引擎。请确保在ASP页面的顶部添加以下代码:<
asp中vbscript.encode错误怎么解决
2024-02-29

python中InternalError错误如何解决

在Python中,InternalError错误通常是由于底层数据库或操作系统发生故障引起的。如果遇到InternalError错误,可以尝试以下解决方法:1. 重新启动程序:尝试退出程序并重新启动,有时这可以解决临时的内部错误。2. 检查
2023-09-22

windows中driverpowerstatefailure错误如何解决

这篇“windows中driverpowerstatefailure错误如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇
2023-07-01

Python中keyerror错误怎么解决

KeyError错误在Python中通常发生在尝试访问字典中不存在的键时。解决该错误的方法如下:1. 确保键存在:在访问字典之前,可以使用`in`关键字来检查键是否存在于字典中。例如:```pythonmy_dict = {'key1':
2023-08-08

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录