JHipster 8.6.0 JDL生成应用,枚举字段获取详情抛类型不匹配异常
问题:JHipster 8.6.0 带枚举与Elasticsearch的实体详情页类型不匹配异常
我使用JHipster 8.6.0基于JDL生成一个单体应用,该应用仅包含一个带枚举值的实体,且启用Elasticsearch搜索引擎。对应的JDL配置如下:
application { config { applicationType monolith authenticationType oauth2 baseName EnumTest buildTool maven cacheProvider hazelcast clientFramework angular clientTheme solar clientThemeVariant dark databaseType sql devDatabaseType postgresql enableHibernateCache true enableSwaggerCodegen true enableTranslation true languages [fr, en] messageBroker false microfrontends [] nativeLanguage fr packageName fr.jhipster.test prodDatabaseType postgresql reactive false searchEngine elasticsearch serviceDiscoveryType no skipUserManagement true testFrameworks [gatling, cucumber, cypress] websocket false withAdminUi true } entities * } entity Address { isoCountryCode IsoCountryCode } enum IsoCountryCode { FRA, ENG, } paginate * with pagination dto * with mapstruct service all with serviceImpl
当尝试查看某条Address的详情时,出现如下异常:
2024-07-22T09:29:35.569+02:00 ERROR 23384 --- [ XNIO-1 task-5] f.m.l.d.web.rest.AddressResource : Exception in getAddress() with cause = 'org.hibernate.PropertyAccessException: Could not set value of type [fr.jhipster.test.domain.enumeration.IsoCountryCode]: 'fr.jhipster.test.domain.Address.isoCountryCode' (setter)' and exception = 'Could not set value of type [fr.jhipster.test.domain.enumeration.IsoCountryCode]: 'fr.jhipster.test.domain.Address.isoCountryCode' (setter)' org.springframework.orm.jpa.JpaSystemException: Could not set value of type [fr.jhipster.test.domain.enumeration.IsoCountryCode]: 'fr.jhipster.test.domain.Address.isoCountryCode' (setter) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:341) at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:241) (...) Caused by: org.hibernate.PropertyAccessException: Could not set value of type [fr.jhipster.test.domain.enumeration.IsoCountryCode]: 'fr.jhipster.test.domain.Address.isoCountryCode' (setter) at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:88) (...) Caused by: java.lang.IllegalArgumentException: Can not set fr.jhipster.test.domain.enumeration.IsoCountryCode field fr.jhipster.test.domain.Address.isoCountryCode to fr.jhipster.test.domain.enumeration.IsoCountryCode at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167) at java.base/jdk.internal.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171) at java.base/jdk.internal.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81) at java.base/java.lang.reflect.Field.set(Field.java:799) at org.hibernate.property.access.spi.SetterFieldImpl.set(SetterFieldImpl.java:57)
问题原因与解决方法
原因
同时使用SQL数据库和Elasticsearch时,JHipster生成的代码会出现枚举类加载冲突:Hibernate从SQL加载的枚举实例,与Elasticsearch处理时使用的枚举类实例来自不同类加载器,JVM会将其视为不同类型,导致反射赋值时抛出类型不匹配异常。
解决方法
在JDL中给枚举字段显式指定存储类型,让Hibernate与Elasticsearch使用一致的枚举处理策略。修改后的实体定义如下:
entity Address { isoCountryCode IsoCountryCode @Enumerated(STRING) }
- 使用
@Enumerated(STRING)会将枚举以字符串形式存储到SQL数据库,同时Elasticsearch也会映射为字符串类型; - 若希望以序号存储,可替换为
@Enumerated(ORDINAL)。
显式指定枚举存储策略后,JHipster生成的实体类会添加对应的JPA注解,Elasticsearch的文档映射也会同步匹配,从根源避免类加载冲突导致的类型不匹配问题。
内容的提问来源于stack exchange,提问作者Pierre Taquet
相关产品推荐
相关产品推荐

