首页 > 解决方案 > 休眠 - @OneToOne 关系

问题描述

我正在尝试建立一对一的关系。在所有者方面,bookIsn(非主)是指目标实体的主键。现在的问题是,如果我想阅读所有评论(reviewRepository.findAll()),如果没有书可用于给定,则会引发以下错误bookIsn

Unable to find com.repository.model.Book with id 1

null但是,如果找不到书,则预期的行为将是书实体简单地设置为。就像我使用reviewIdfor 加入列@JoinColumn( name = "review_id", ... )而不是review_isn.

有人可以解释为什么它使用主键,而不是非主属性吗?需要做什么才能使其也适用于非主要属性?

下面两个类:

审查.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;
}

书.java:

@Entity
@Data
@Table(name = "book")
public class Book {

  @Id
  @Column(name="book_isn")
  private String bookId;

  @Column(name="book_name")
  private String bookName;

}

标签: javahibernateone-to-one

解决方案


首先我不得不说,我不建议你将@Datalombok 注释与 hibernate 实体类一起使用。例如见这篇文章。

然后,我建议您以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

PS 另请注意,由于潜在的性能问题,不建议将字符串用作大表的主键类型。


推荐阅读