WelcomeTo
WelcomeTo

Reputation: 20571

Map @ElementCollection to same table

I want Hibernate to build for me only 1 table with this columns:

id | product_id | enum_id
1    1            1 
2    1            2

I.e. each product can have many enums. And I don't want to introduce new linking table.

So my question is how to annotate my fields to achieve such table structure.

So far I have this entity:

@Entity
public class Entity {

   @Id
   private Long id;

   @ManyToOne( fetch = FetchType.LAZY )
   @JoinColumn( name = "product_id" )
   private Product product;     

   @ElementCollection
   @??? // what should go here? 
   private List<Enum> enums = new Arralist<>();
}

Upvotes: 2

Views: 3053

Answers (2)

Tobias Liefke
Tobias Liefke

Reputation: 9022

Your proposed table will have exactly one product and one enum per Entity instance. This has nothing to do with your annotations, but with the fact that an entity will always generate a new instance for each row, because every row has its own ID.

If you drop the ID column, than the given table is already your linking table and you simply need to annotate the Product entity:

@Entity
public class Product {
  // ...

  @ElementCollection
  @Enumerated
  private Set<MyEnum> enums;

}

You will need to declare the type of the Enum, in my example MyEnum, as you can't bind to any Enum (Hibernate wouldn't know which one to instantiate when reading from the database).

If you want to stick to any existing table or column names you can use the additional @CollectionTable. But I would propose to use the defaults, as it makes the code easier to read.

And if you really, as in your first attempt, need a list of enums (which allows duplicates and stores the ordering of items), than you need an additional column for the index in the list. You can achieve this with:

@ElementCollection
@Enumerated
@OrderColumn
private List<MyEnum> enums;

Upvotes: 1

m.aibin
m.aibin

Reputation: 3593

I can see that you will add multiple rows with different values, so why not go like this:

@Entity
public class Entity {

  @Id
  private Long id;

  @ManyToOne( fetch = FetchType.LAZY )
  @JoinColumn( name = "product_id" )
  private Product product;     

  @Enumerated(EnumType.STRING)
  private Enum enum;

and then you can add multiple enums connected to product_id in multiple rows. If you want to have only one position for each product, that you can use approach mentioned by @StanislavL:

@ElementCollection
@CollectionTable(name="the_table_name", joinColumns=@JoinColumn(name="product_id")) @Column(name="product_id")
private Enum enum;

Upvotes: 0

Related Questions