我正在尝试建立一对一的关系。在所有者方面,bookIsn
(非主键)是指目标实体的主键。
现在的问题是,如果我想阅读所有评论 (reviewRepository.findAll()
),如果给定的 bookIsn
没有可用的书籍,则会引发以下错误:
Unable to find com.repository.model.Book with id 1
但预期行为是,如果找不到书,则书实体仅设置为 null
。就像我使用 reviewId
加入列 @JoinColumn( name = "review_id", ... )
而不是 review_isn
一样。
有人可以解释为什么它使用主键而不是非主属性吗?需要做什么才能使其也适用于非主要属性?
下面两个类:
Review.java:
@Entity
@Data
@Table(name = "review")
public class Review {
@Id
@Column(name="review_id")
private String reviewId;
@Column(name="book_isn")
private String bookIsn;
@OneToOne
@JoinColumn(
name = "book_isn",
referencedColumn = "book_isn",
insertable = false,
updatable = false)
private Book book;
}
Book.java:
@Entity
@Data
@Table(name = "book")
public class Book {
@Id
@Column(name="book_isn")
private String bookId;
@Column(name="book_name")
private String bookName;
}
答案 0 :(得分:1)
首先我要说的是,我不建议您在 hibernate 实体类中使用 @Data
lombok 注释。参见示例 this 文章。
然后,我建议您以这种方式更正您的 Review
实体映射:
import javax.persistence.Transient;
@Entity
@Table(name = "review")
public class Review
{
private String reviewId;
private Book book;
@Id
@Column(name = "review_id")
public String getReviewId()
{
return reviewId;
}
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "book_isn")
public Book getBook()
{
return book;
}
// setters omitted for brevity
@Transient
public String getBookId()
{
return book != null ? book.getBookId() : null;
}
}
您可以通过以下方式保留您的 Review
实体:
Book b1 = new Book();
b1.setBookId("BK1");
b1.setBookName("Book 1");
Review r1 = new Review();
r1.setReviewId("R1");
r1.setBook(b1);
session.persist(r1);
Review r2 = new Review();
r2.setReviewId("R2");
session.persist(r2); // book_isn is NULL for the R2 Review
附言另请注意,由于潜在的性能问题,it is not recommended 使用字符串作为大表的主键类型。