PersistentEnum should use proper mappedClass as returnedClass()
Closed this issue · 2 comments
Antonnz commented
Entity:
@Entity
public class Promo {
@Type(type = "org.jadira.usertype.corejava.PersistentEnum", parameters = @Parameter(name = "enumClass", value = "id.co.bippo.common.PromoKind"))
private PromoKind kind = null;
@Type(type = "org.jadira.usertype.corejava.PersistentEnum", parameters = @Parameter(name = "enumClass", value = "id.co.bippo.promotion.jpa.PromoScope"))
private PromoScope scope = null;
To use NEW with the following class:
public class PromoWithPositioner {
public PromoWithPositioner(UUID id, PromoKind kind, @Nullable PromoScope scope, Integer positioner) {
super();
this.id = id;
this.kind = kind;
this.scope = scope;
this.positioner = positioner;
}
and the following query:
final String query = "SELECT NEW id.co.bippo.promotion.impl.PromoWithPositioner(p.id, p.kind, p.scope, p.positioner)"
+ " FROM Promo p";
final List<PromoWithPositioner> unsorted = em.createQuery(query, PromoWithPositioner.class).getResultList();
Hibernate complains:
org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [id.co.bippo.promotion.impl.PromoWithPositioner]. Expected arguments are: java.util.UUID, java.lang.Enum, java.lang.Enum, int [SELECT NEW id.co.bippo.promotion.impl.PromoWithPositioner(p.id, p.kind, p.scope, p.positioner) FROM id.co.bippo.promotion.jpa.Promo p]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:91)
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:109)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:284)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:131)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:93)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1800)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:342)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:291)
at com.sun.proxy.$Proxy141.createQuery(Unknown Source)
at id.co.bippo.promotion.impl.JpaPromoRepository.findAllWithPositioner(JpaPromoRepository.java:426)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:267)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy149.findAllWithPositioner(Unknown Source)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.apache.wicket.proxy.LazyInitProxyFactory$JdkHandler.invoke(LazyInitProxyFactory.java:435)
at com.sun.proxy.$Proxy191.findAllWithPositioner(Unknown Source)
at id.co.bippo.promotion.web.ActionPromoLinkPanel$2.onClick(ActionPromoLinkPanel.java:90)
IMHO this is not correct, as when getting e.g. p.kind
Hibernate knows that it is using user type PersistentEnum[enumClass=id.co.bippo.promotion.jpa.PromoKind]
, and getMappedClass()
returns id.co.bippo.promotion.jpa.PromoKind
.
However, returnedClass()
should return getMappedClass()
instead:
@Override
public Class<Enum<?>> returnedClass() {
return (Class<Enum<?>>) getMappedClass();
}
There is a workaround, which uses Hibernate's expected signature:
public PromoWithPositioner(UUID id, Enum<PromoKind> kind, @Nullable Enum<PromoScope> scope, Integer positioner) {
super();
this.id = id;
this.kind = (PromoKind) kind;
this.scope = (PromoScope) scope;
this.positioner = positioner;
}
Tag @ceefour
ceefour commented
👍 for this :)
chrisphe commented
There is a fix for this about to be pushed to HEAD in GitHub