hibernate 使用第二个字段用于实体中的相同列,用于散列代码等于和实体管理

qyzbxkaa  于 2023-06-23  发布在  其他
关注(0)|答案(1)|浏览(109)

我们在项目中使用spring data jpa和hibernate。
以下是实体的示例表示。

@Entity
public class Author {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long authorId;
 
    private String firstName;
 
    @OneToOne(mappedBy = "author")
    private Book book;

 
    ...
}

@Entity
public class Book {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    private String title;
 
    @OneToOne(fetch= FetchType.LAZY)
    private Author author;

    ...
}

请原谅任何语法问题。
我们只有OneToOne关联字段,这对我们的设计有很多缺点。
1.作者总是懒洋洋地拿来。
1.我们用作者ID唯一标识Book
1.我们在book表中有authorId作为外键。
1.如果你仔细理解,我们不能使用authorId来唯一地标识记录,仅仅是因为hibernate懒惰的关联,即使我们想使用它,在equals和hashcode合约中。如果我们在equals和hashcode中使用author关联,它会急切地为我们不想要的每本书调用author实体。
1.在这里,我们之前遇到了一个障碍,因为book.author.authorId被用在太多的地方,这需要额外的join或查询author表来获取 * only id *。

    • 为了解决这个问题,我们在Book实体中创建了另一个字段authorId。**
  • 有了这个字段,我们可以在所有查询中执行类似book.authorId的操作,而无需获取作者实体。
  • 这是我们在许多论坛中提到的将insertableupdateable设置为false的方法,以便将单个列Map到多个字段。
@Entity
public class Book {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
 
    private String title;
 
    @OneToOne
    private Author author;
    
    @Column(name = "authorId", insertable = false,updatable = false)
    private Long authorId

    ...
}
    • 到目前为止,我已经测试了以下内容:**

1.使用authorId获取工作正常。
1.它与hql jpql一起工作,带有基本测试
1.但不确定限制。

    • 问题:**

1.我所理解的是这个字段是只读的,由hibernate为我设置,我不应该明确地在任何地方更新这个字段,我的理解正确吗?
1.在hql/jpql和sql查询中,我们是否可以安全地使用authorId作为新字段

  1. hibernate会正确管理此字段吗?
    1.我们是否需要显式地设置它?当我创建Book时,我可以这样做
Author author = repository.findById();
Book b = new Book();
b.setAuthor(author)
b.setAuthorId(author.getId)

还有任何其他情况下,我显式地需要设置book.authorId?那么它会被Hibernate正确管理吗?

w80xi6nr

w80xi6nr1#

1.我所理解的是这个字段是只读的,由hibernate为我设置,我不应该明确地在任何地方更新这个字段,我的理解正确吗?
是的,一旦相同的字段用于关联,您就不能触摸它。如果你需要更新数据库中的值,你必须通过更新Book.author来完成。在您的实体中,只需在Booke实体中创建一个私有setter,以确保该字段不会被触及。
1.在hql/jpql和sql查询中,我们是否可以安全地使用authorId作为新字段
你可以,但你可能不应该。在你上面的问题中,你写道:
在这里,我们之前遇到了一个障碍,因为book.author.authorId在太多的地方被使用,这需要额外的连接或查询author表,只是为了获得id。
如果你查看生成的代码,你会发现没有生成join子句,因为Hibernate足够聪明,可以从Books表的author_id列中获取值。也就是说,如果你写JPQL查询像

select book from Book book where book.author.auhtorId = :authorId

结果查询将是

select b.* from books b where b.author_id = ?`
  1. hibernate会正确管理此字段吗?
    是的,Hibernate主要依赖于反射,所以即使使用私有访问器,代码也是正确的。
    1.我们是否需要显式地设置它?
    不,你不必这样做.您需要关心Book.author,因为它是关联实体。只要Book.authorId被注解为@Column(name = "authorId", insertable = false,updatable = false),Hibernate就不会期望你更新它,就你的代码而言,这就足够了:
Author author = repository.findById();
Book b = new Book();
b.setAuthor(author)

P.S.在上面的代码片段中,你可以使用Author author = repository.getById();而不是Author author = repository.findById();来保存一个DB调用,因为JpaRepository.getById()返回一个带有id的代理,而不是实际获取数据。

相关问题