Reputation: 181
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
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
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
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
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