单向和双向的Hibernate关系混淆

wztqucjr  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(145)

我有SpringDataJPA的经验,但是对Hibernate是新的,在看了几个教程和文章之后,现在我对一些问题太困惑了。你能澄清我下面的问题吗?

**1.**关于OneToMany关系,建议在表(例如Country表)中定义此关系,而不是在相关表(例如具有country_idMap关键字的Employee表)中定义此关系。但是,此关系与其他关系有不同类型的实现。

在Hibernate中单向或双向关系意味着什么?
为了理解Hibernate中使用的所有关系,你能给我一个例子或者给我一个好的例子吗?

**2.**对于ManyToMany关系,一些示例使用List<T>,而另一些示例使用Set<T>Collection<T>。那么,定义多个关系实体的正确方法是什么?
**3.**还有一些不必要的实现,例如@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "book_id"),因为这些是默认实现。因此,就我所见,没有必要暗示这些默认设置,因为它们没有影响。是这样吗?

sqxo8psd

sqxo8psd1#

因为有许多不同的使用案例,所以有许多选项。
1.在Bidirectional和uni之间进行选择会影响到Java对象Map实体、关联如何Map到数据库以及Hibernate将使用哪个查询来加载实体(或转换HQL查询)。我不会详细介绍所有内容-文档已经做得很好了-但是如果我们采用以下双向关联:

@Entity(name = "Person")
@Table(name="PERSON_TABLE")
class Person {

  @Id    
  private Long id;

  @OneToMany(mappedBy = "person")
  private List<Phone> phones = new ArrayList<>();

}

@Entity
@Table(name="PHONE_TABLE")
class Phone {

  @Id    
  private Long id;

  @ManyToOne
  private Person person;

}

Hibernate将Map它,在表PHONE_TABLE上添加一列person_id
如果我们将其Map为单向一对多:

@Entity(name = "Person")
@Table(name="PERSON_TABLE")
class Person {

  @Id    
  private Long id;

  @OneToMany(mappedBy = "person")
  private List<Phone> phones = new ArrayList<>();

}

@Entity
@Table(name="PHONE_TABLE")
class Phone {

  @Id    
  private Long id;

  // No many-to-one in this class

}

Hibernate会创建一个额外的表Person_PhonePHONE_TABLEPERSON_TABLE之间的桥梁),其中包含两列person_idphone_id
1.这取决于您希望关联包含的内容类型以及返回的方式:它有重复项吗?它是有序的吗?您希望得到数据库上显示的结果还是希望在集合上使用可比较的?您使用的是哪种Map?List通常是一个很好的通用选项,但在某些情况下使用其他实现可能会有更好的性能,比如当您需要多对多关联或者当您希望急切地加载多个关联时。这个关于堆栈溢出的问题解释了为什么one cannot load multiple lists eagerly和文档列出了所有可用的集合(在线有更多的文章)。
单向袋在改变收集结构(去除或重新洗牌元件)时效率不高。
由于父项端无法唯一识别每个个别子项,因此Hibernate会删除与父实体相关的所有链接数据表数据列,并重新加入在目前集合状态中找到的其馀数据列。

  1. @JoinColumn是可选的,当用户要更改某些默认值时,通常需要使用它。例如,当您要更改Map关联的列名时:
@Entity
class Book {

   // Default column name would be `author_id` but we change it to `a_id`,
   // if you are fine with author_id, than `@JoinColumn` is not necessary
   @ManyToOne
   @JoinColumn(name = "a_id")
   Author author;
}

对于@ManyToOne(fetch = FetchType.LAZY),Hibernate不能总是延迟地获取多对一的关联,所以默认值是EAGER。当Hibernate延迟地加载一个关联时,它会创建一个所需类的代理对象。问题是,您可能会有如下代码:

Book book = session.find(Book.class, 5);
if ( book.getAuthor() == null ) {
 // do something ...
}

如果Hibernate每次都创建一个代理,那么getAuthor()永远不会返回null,所以如果Hibernate不用查询关联的表就能猜到作者存在,它就会懒洋洋地加载它(例如,当指定关联总是存在时),否则它只会查询关联的表并急切地创建对象。

相关问题