【问题标题】:How to persist an object that has an enumeration field如何持久化具有枚举字段的对象
【发布时间】:2011-05-13 22:47:32
【问题描述】:

我在我的域模型中使用枚举,但是当我尝试将对象持久保存到数据库时出现以下错误:

线程“主”java.lang.ClassCastException 中的异常:nl.ru.cmbi.pdbeter.core.model.enums.Enum_WhifFunction 无法转换为 java.lang.String 在 org.hibernate.validator.NotEmptyValidator.isValid(NotEmptyValidator.java:36) 在 org.hibernate.validator.ClassValidator.getInvalidValues(ClassValidator.java:386) 在 org.hibernate.validator.ClassValidator.getInvalidValues(ClassValidator.java:352) 在 org.hibernate.validator.event.ValidateEventListener.validate(ValidateEventListener.java:139) 在 org.hibernate.validator.event.ValidateEventListener.onPreInsert(ValidateEventListener.java:172) 在 org.hibernate.action.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:142) 在 org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:65) 在 org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) 在 org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:321) 在 org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204) 在 org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:130) 在 org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210) 在 org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195) 在 org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117) 在 org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93) 在 org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535) 在 org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527) 在 org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523) 在 nl.ru.cmbi.pdbeter.core.controller.DAO.GenericDAO.makePersistent(GenericDAO.java:73) 在 nl.ru.cmbi.pdbeter.core.controller.DAO.WhifFunctionDAO.getWhifFunctionSet(WhifFunctionDAO.java:36) 在 nl.ru.cmbi.pdbeter.core.controller.DAO.LoggedErrorWhifDAO.updateWhifFunctionSet(LoggedErrorWhifDAO.java:42) 在 nl.ru.cmbi.pdbeter.whifclient.controller.WhifFunctionsUpdater.executeWhifFunctionsByAccessionCode(WhifFunctionsUpdater.java:93) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:616) 在 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 在 $Proxy31.executeWhifFunctionsByAccessionCode(未知来源) 在 nl.ru.cmbi.pdbeter.whifclient.controller.WhifFunctionsExecutor.executeWhifFunctions(WhifFunctionsExecutor.java:26) 在 nl.ru.cmbi.pdbeter.whifclient.controller.WhifClient.updateWhifFunctions(WhifClient.java:22) 在 nl.ru.cmbi.pdbeter.updater.controller.UpdaterMain.start(UpdaterMain.java:65) 在 nl.ru.cmbi.pdbeter.updater.controller.UpdaterMain.main(UpdaterMain.java:44)

这是我的领域模型:

package nl.ru.cmbi.pdbeter.core.model.domain;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.ManyToMany;

import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import nl.ru.cmbi.pdbeter.core.model.enums.Enum_WhifFunction;

import org.hibernate.annotations.NaturalId;
import org.hibernate.validator.NotEmpty;

@Entity
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(callSuper = false, of = { "whifFunction" })
@SuppressWarnings("PMD.UnusedPrivateField")
public class WhifFunction extends DomainObject implements Serializable {
    @NaturalId
    @NotEmpty
    @Enumerated(EnumType.STRING)
    private Enum_WhifFunction           whifFunction;

    @ManyToMany(mappedBy = "whifFunctionSet", cascade = CascadeType.ALL)
    private Set<LoggedErrorWhif> loggedErrorWhifSet = new HashSet<LoggedErrorWhif>();

    public WhifFunction(Enum_WhifFunction whifFunction) {
        if (whifFunction == null) {
            throw new IllegalStateException("WhifFunction is null");
        } else {
            this.whifFunction = whifFunction;
        }
    }

    @Override
    public String toString() {
        return whifFunction.toString();
    }
}

为什么@Enumerated 注释没有像我认为的那样工作?如果它按预期工作,我怎样才能让它按照我现在认为的方式工作?或者换句话说:如何持久化具有枚举字段的对象。

编辑: 感谢所有的答案。 NotEmpty 是偶然出现的,我没看到。我必须进行很多映射,所以我复制粘贴了很多东西,但是当我从字符串更改为枚举时不小心忘记删除 NotEmpty。下次我尝试更仔细地查看堆栈跟踪时,我完全错过了 NotEmptyValidator。

【问题讨论】:

  • 请显示完整的堆栈跟踪。
  • 请提供 SSCCE。顺便说一句,Enum_WhifFunction 不遵循 Java 命名约定。我建议去掉下划线。

标签: java hibernate persistence enumeration


【解决方案1】:

问题是验证器而不是映射!

at org.hibernate.validator.NotEmptyValidator.isValid(NotEmptyValidator.java:36)

注解@NotEmpty 包含@Size(min = 1)@Size 仅支持 String、Collection、Map 和 Array。

【讨论】:

  • 所以用@NotNull 替换@NotEmpty
【解决方案2】:

我认为如果您将 @NotEmpty 更改为 @NotNull 它应该可以工作。使用字符串的 NotEmpty 应该等同于:

string != null && string.trim().length() > 0

@Enumerated 与String 一起使用应该将Enum_WhifFunction.name() 持久化为存储的db 值,因此相反它应该使用Enum_WhifFunction.valuOf(storedValue) 将字符串值传输回枚举。

这个问题可能是因为验证器可能试图做这样的事情:

Object o = //get field
String toValidate = (String) o; // throws a class cast if o is of type Enum_WhifFunction
return toValidate != null && toValidate.trim().length() > 0;

【讨论】:

    【解决方案3】:

    java.lang.ClassCastException:nl.ru.cmbi.pdbeter.core.model.enums.Enum_WhifFunction 无法转换为 java.lang.String 在 org.hibernate.validator.NotEmptyValidator.isValid(NotEmptyValidator.java:36)

    @NotEmpty 似乎是问题的来源而不是@Enumerated 注释...

    【讨论】:

      【解决方案4】:

      看看Mapping enum types with Hibernate Annotations可能会有所帮助。

      从那里的示例看起来你应该有:

      private Enum_WhifFunction           whifFunction;
      @Enumerated(EnumType.STRING)
      public Enum_WhifFunction getWhifFunction() {
        return this.whifFunction;
      }
      

      【讨论】:

      • 他们在那里展示的与我在这里展示的有何不同?仍然在我的代码中,它似乎不起作用。当我回到家时,我会尝试 EnumType.ORDINAL 看看这是否可以解决问题。我仍然希望枚举的字符串表示形式存在于数据库中,而不是数字,以防有人直接在数据库中查找。
      【解决方案5】:

      显然 Enum_WhifFunction 不能转换为字符串。 可以发一下 Enum_WhifFunction 代码吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-22
        • 2011-01-20
        • 1970-01-01
        相关资源
        最近更新 更多