plcstpierre
plcstpierre

Reputation: 181

How to specify a Primary Key on @ElementCollection

So, there is that behavior with innodb that can cause problem if some tables lack of primary key.

So with Hibernate, I am looking for a key to specifies a primary key on a @ElementCollection table with a Set as the underling data structure.

I found a way to have a primary key with a map, but it is kind of weird because I do not need a map.

I also found an answer related to @Embeddable, but I do not need that kind of complexities. I am using a Set or Set as the data structure in my entities.

Any idea how to achieve that?

Upvotes: 12

Views: 12943

Answers (4)

Guram Kankava
Guram Kankava

Reputation: 61

This example is from a book java persistence with spring data and hibernate, dose not work for a Set, but works for java.util.Collection.Collection or List

@org.hibernate.annotations.GenericGenerator(name = "sequence_gen", strategy = "sequence")
@org.hibernate.annotations.CollectionId(column = @Column(name = "NAME_ID"), type = @Type( type = "long"), generator = "sequence_gen" )
@CollectionTable(schema = "", name = "NAMES", joinColumns = @JoinColumn(name = "ROOT_ID"))
@ElementCollection
private List<String> names = new ArrayList<>();

Upvotes: 0

kinjelom
kinjelom

Reputation: 6450

Tested on Spring Boot / Data JPA 2.5.2, hibernate-core 5.4.32:

@Entity
@Table(name = "user")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Data
@NoArgsConstructor
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ElementCollection(fetch = FetchType.EAGER, targetClass = Role.class)
    @Enumerated(EnumType.STRING)
    @CollectionTable(
        name = "user_role",
        joinColumns = @JoinColumn(name = "user_id")
    )
    @Column(name = "role", nullable = false)
    private Set<Role> roles; // public enum Role {ADMIN,USER}
}

produces MySQL table:

CREATE TABLE `user_role` (
  `user_id` bigint(20) NOT NULL,
  `role` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`user_id`,`role`),
  CONSTRAINT `FK_random_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
)

Upvotes: 0

David L
David L

Reputation: 44657

If you use a Set and make the element Column be not null, then hibernate will make a primary key with the join column and element column.

Example:

@Column(name = "STRINGS", nullable = false)
@ElementCollection
private Set<String> strings;

Upvotes: 18

Vlad Mihalcea
Vlad Mihalcea

Reputation: 153800

@ElementCollection cannot take a primary key, because an Embeddable types cannot have an identifier.

You can add an @OrderColumn to optimize the generates SQL statements.

If you need a primary key, then you should turn the @ElementCollection into a @OneToMany association.

Upvotes: 6

Related Questions