I’m using SpringBoot with JPA and Hibernate.
I have two entities: Book and Author. A Book can have multiple Authors. So I need a OneToMany relationship.
Into the Author table, my idea is to use a composite key (the book_id and one internal field for example field_a)
I implemented these classes:
@Entity @Table(name = "book") public class Book extends MyBaseEntity { @Id @Column(name = "id") @Type(type = "uuid-char") private UUID uuid = UUID.randomUUID(); @Column(name = "name", nullable = false) private String name; @OneToMany(mappedBy = "book") private List<Author> authors = new ArrayList<>(); } @Entity @Table(name = "author") public class Author extends MyBaseEntity { @EmbeddedId private CustomID id; @ManyToOne() @MapsId("bookId") @JoinColumn(name = "book_id") private Book book; @Column(name = "field_a", nullable = false) @MapsId("fieldA") @Type(type = "uuid-char") private UUID fieldA; } @Embeddable public class CustomID implements Serializable { @Column(name = "book_id") private UUID bookId; @Column(name = "field_a") private UUID fieldA; public CustomID() { } public CustomID(UUID bookId, UUID fieldA) { this.bookId = bookId; this.fieldA = fieldA; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ShareID that = (CustomID) o; return Objects.equals(bookId, that.bookId) && Objects.equals(fieldA, that.fieldA); } @Override public int hashCode() { return Objects.hash(bookId, fieldA); } }
When I try to execute my project (I’m using the property spring.jpa.hibernate.ddl-auto=create
to generate the DB) I’m obtaining this error:
ERROR SpringApplication-reportFailure():837 - [ Application run failed ] org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.AnnotationException: Unknown entity name: java.util.UUID
Any suggestion?
If I try to remove the use of composite-key works fine so, probably the problem it’s related to the implementation or use of the composite key.
Advertisement
Answer
Use either an ID class with Author as:
@Entity @Table(name = "author") @IdClass(CustomID.class) public class Author extends MyBaseEntity { @Id @ManyToOne() @JoinColumn(name = "book_id") private Book book; @ID @Column(name = "field_a", nullable = false) @Type(type = "uuid-char") private UUID fieldA; } public class CustomID implements Serializable { //these match the names of the property marked with @Id in Author private UUID book; private UUID fieldA; }
Or an embeddable that defines the basic fields for your entity as you have already done:
@Entity @Table(name = "author") public class Author extends MyBaseEntity { @EmbeddedId private CustomID id; @ManyToOne() @MapsId("bookId") @JoinColumn(name = "book_id") private Book book; }