2

i want to use an enum in an entity bean. But the enum is in an embedded object. There is the code:

@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;
   }
}

My Embedded Object includes the enum and looks like this:

@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;
    }
}

In the table entity_foo i declared the value enumbar as varchar(255). Now i try to get data from the database.

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

This throws an PSQLException:

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

If i use the enum directly in the entity "EntityFoo" it works fine. This code runs on Wildfly 8.1 with Postgres 9.3 and Java 1.7

I hope i declared my problem clearly and anyone can help me.

UPDATE

Here is the link to a miniproject repository https://github.com/MotherCake/miniprojct

To use this project you need a table. Here is the create statement.

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');

What i forgot to mention is that i'm using Toplink. I think Toplink causes the problem.

In the class Testservlet you can see 2 different ways to create a query. The exception i described is thrown if i use the createQuery(..) method with the setParameter(..) method. This is in the comment.

If i'm using the method createNativeQuery i get the result list and no exception is thrown. But after that i get a ClassCastException in class TestServlet.

sylo
  • 207
  • 3
  • 16

2 Answers2

1

The problem is that by default enums are persisted as int using oridinal. You have to change it to String representation by adding @Enumerated(EnumType.STRING) on enum field. Also check that in your main entity you've annotated fields instead of getter/setter so it turns on FIELD access on the entity as well as on embedded entity (in this case EmbeddedFoo). So if you annotate in EmbeddedFoo field instead of getter it will works correctly.

@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;
    }
}

Also if you must have annotation on the getter for some reason you have to annotate EmbeddedFoo by @Access(AccessType.PROPERTY) and it'll also fix your problem.

@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;
    }
}
Jakub Kubrynski
  • 13,724
  • 6
  • 60
  • 85
0

I found a solution to get the project work, but i dont know why this is necassary. I thought, as Jakub wrote, that adding @Enumerated(EnumType.STRING) should be enough.

I annotated the variable enumBar with @Column(name = "enumbar").

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

Furthermore i add the @AtributeOverride annotation to the embedded object in EntityFoo

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

After that it works like charm.

I update the project on github for everyone who would like to try out.

Thanks for help.

sylo
  • 207
  • 3
  • 16