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:
JavaScript
x
@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:
JavaScript
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:
JavaScript
@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:
JavaScript
@Entity
@Table(name = "author")
public class Author extends MyBaseEntity {
@EmbeddedId
private CustomID id;
@ManyToOne()
@MapsId("bookId")
@JoinColumn(name = "book_id")
private Book book;
}