2

我想在实体 bean 中使用枚举。但是枚举是在一个嵌入的对象中。有代码:

@Entity
@Table(name = "entity_foo")
public class EntityFoo implements Serializable
{
   @Embedded
   private EmbeddedFoo embeddedFoo;

   public EmbeddedFoo getEmbeddedFoo()
   {
      return embeddedFoo;
   }

   public void setEmbeddedFoo(final EmbeddedFoo embeddedFoo)
   {
      this.embeddedFoo = embeddedFoo;
   }
}

我的嵌入式对象包括枚举,如下所示:

@Embeddable
public class EmbeddedFoo implements Serializable
{
    public static enum EnumBar {
        VALUEA,VALUEB
    }

    private EnumBar enumBar;

    @Enumerated(EnumType.STRING)
    public EnumBar getEnumBar()
    {
        return enumBar;
    }

    public void setEnumBar(final EnumBar enumBar)
    {
        this.enumBar = enumBar;
    }
}

在表 entity_foo 中,我将值 enumbar 声明为 varchar(255)。现在我尝试从数据库中获取数据。

final List<EntityFoo> entityFoos = query.getResultList();

这将引发 PSQLException:

Caused by: org.postgresql.util.PSQLException: Bad value for type int : VALUEA

如果我直接在实体“EntityFoo”中使用枚举,它工作正常。此代码在 Wildfly 8.1 上运行,带有 Postgres 9.3 和 Java 1.7

我希望我清楚地声明了我的问题,任何人都可以帮助我。

更新

这是一个小型项目存储库的链接 https://github.com/MotherCake/miniprojct

要使用这个项目,您需要一张桌子。这是创建语句。

CREATE TABLE "public"."minitable"(id int PRIMARY KEY NOT NULL,enumbar varchar(255));
CREATE UNIQUE INDEX minitable_pkey ON "public"."minitable"(id);
INSERT INTO minitable (id,enumbar) VALUES (0,'VALUEA');
INSERT INTO minitable (id,enumbar) VALUES (1,'VALUEB');

我忘了提到的是我正在使用 Toplink。我认为Toplink会导致问题。

在 Testservlet 类中,您可以看到创建查询的 2 种不同方法。如果我将 createQuery(..) 方法与 setParameter(..) 方法一起使用,则会引发我描述的异常。这是在评论中。

如果我使用 createNativeQuery 方法,我会得到结果列表并且不会引发异常。但在那之后,我在类 TestServlet 中得到了一个 ClassCastException。

4

2 回答 2

1

问题是,默认情况下,枚举使用 oridinal 持久化为 int。您必须通过添加@Enumerated(EnumType.STRING)枚举字段将其更改为字符串表示形式。还要检查您的主实体中是否已注释字段而不是 getter/setter,以便它打开实体以及嵌入式实体(在本例中为 EmbeddedFoo)上的 FIELD 访问。因此,如果您在 EmbeddedFoo 字段而不是 getter 中进行注释,它将正常工作。

@Embeddable
public class EmbeddedFoo implements Serializable
{
    public static enum EnumBar {
        VALUEA,VALUEB
    }

    @Enumerated(EnumType.STRING)
    private EnumBar enumBar;

    public EnumBar getEnumBar()
    {
        return enumBar;
    }

    public void setEnumBar(final EnumBar enumBar)
    {
        this.enumBar = enumBar;
    }
}

此外,如果由于某种原因必须在 getter 上添加注释,则必须通过 @Access(AccessType.PROPERTY) 注释 EmbeddedFoo,它也可以解决您的问题。

@Embeddable
@Access(AccessType.PROPERTY)
public class EmbeddedFoo implements Serializable
{
    public static enum EnumBar {
        VALUEA,VALUEB
    }

    private EnumBar enumBar;

    @Enumerated(EnumType.STRING)
    public EnumBar getEnumBar()
    {
        return enumBar;
    }

    public void setEnumBar(final EnumBar enumBar)
    {
        this.enumBar = enumBar;
    }
}
于 2014-08-04T14:59:44.057 回答
0

我找到了让项目工作的解决方案,但我不知道为什么这是必要的。正如 Jakub 所写,我认为添加@Enumerated(EnumType.STRING)就足够了。

我用 @Column(name = "enumbar") 注释了变量 enumBar。

@Column(name = "enumbar")
@Enumerated(EnumType.STRING)
public EnumBar enumBar;

此外,我将 @AtributeOverride 注释添加到 EntityFoo 中的嵌入对象

@Embedded
@AttributeOverride(name = "enumBar", column = @Column(name = "enumbar"))
private EmbeddedFoo embeddedFoo;

之后,它就像魅力一样。

我为所有想尝试的人更新了 github 上的项目。

感谢帮助。

于 2014-08-07T11:54:56.970 回答