Wildfly - 在可嵌入的bean中使用枚举

时间:2014-08-04 14:54:29

标签: java enums toplink wildfly-8

我想在实体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”中使用枚举,它可以正常工作。此代码在带有Postgres 9.3和Java 1.7的Wildfly 8.1上运行

我希望我能清楚地宣布我的问题,任何人都可以帮助我。

更新

这是微型项目存储库的链接 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类中,您可以看到两种不同的方法来创建查询。如果我使用setParameter(..)方法使用createQuery(..)方法,则抛出我描述的异常。这是在评论中。

如果我正在使用createNativeQuery方法,我会得到结果列表并且不会抛出任何异常。但之后我在类TestServlet中得到了ClassCastException。

2 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分: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上为每个想要试用的人更新项目。

感谢您的帮助。