Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate 试图理解ORM中一对多关系的拥有方的重要性_Hibernate_Orm_Playframework_Many To One - Fatal编程技术网

Hibernate 试图理解ORM中一对多关系的拥有方的重要性

Hibernate 试图理解ORM中一对多关系的拥有方的重要性,hibernate,orm,playframework,many-to-one,Hibernate,Orm,Playframework,Many To One,尽管我的问题是专门针对使用Hibernate的Play框架中实体关系的描述方式,但我确信这是一个通用概念 当我们有一对多关系时,我们总是被要求指定拥有方 例如,如果我们在Person和PhoneNumber之间有一对多的关系,我们会这样编写代码 @Entity class Person { @OneToMany(mappedBy="person") public Set<PhoneNumber> phoneNumbers; } @Entity class Phone

尽管我的问题是专门针对使用Hibernate的Play框架中实体关系的描述方式,但我确信这是一个通用概念

当我们有一对多关系时,我们总是被要求指定拥有方

例如,如果我们在Person和PhoneNumber之间有一对多的关系,我们会这样编写代码

@Entity
class Person {
    @OneToMany(mappedBy="person")
    public Set<PhoneNumber> phoneNumbers;
}

@Entity
class PhoneNumber {
    @ManyToOne
    public Person person;
}
@实体
班主任{
@OneToMany(mappedBy=“person”)
公共电话号码;
}
@实体
类电话号码{
@许多酮
公众人物;
}
在上面的代码中,拥有实体是PhoneNumber。任何一方作为拥有实体的利弊是什么

我意识到,当拥有实体是PhoneNUmber时,表示的关系是manyTone,这不会产生联接表,而当拥有方是Person时,表示的关系将是OneToMany,在这种情况下,将创建一个关系表

这是决定拥有方的主要原因,还是还有其他原因

更新:
我刚刚意识到这提供了部分答案,但我希望可能还有其他问题。

对于大多数ORM层,您都有延迟加载的概念。创建Person对象时,除非请求,否则不会加载电话集。有时,您希望如何查找数据也可以决定如何存储数据

比如,若你们想先打电话给对方,然后按需显示电话号码,那个么在电话里保留对方的参考资料就可以了。首先启动一个简单的查询来加载person数据,然后根据(已加载的)person.id查找电话号码(另一个简单查询)

而对于一次性显示person+phone数据,您更希望有一个联接表,在该表中,您可以使用person id作为键,根据person表+person phone联接表将数据一次性加载到phone表中。在这里,如果没有关系表进行查找,成本会很高


但是非常坦率地说,如果您认为是SQL而不是ORM,那么每次都会使用关系表:D

需要记住的一点是,拥有的关系实际上是在保存时保持关系的关系。举个例子:

    Person person = new Person();
    PhoneNumber pn = new PhoneNumber();
    pn.phone = "12345678";
    person.phoneNumbers.add(pn);
    session.save(person);
如果从数据库中重新加载实体,将看不到任何数字,则该关系不是save-infact。要实际添加关系,您需要在所有者一侧设置人员(电话号码),然后保存

    // the relation is not saved
    Person loadedPerson = (Person)session.load(Person.class, person.id);
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 0!

    pn.person = person;
    session.save(pn);

    loadedPerson = (Person)session.load(Person.class, person.id);
    System.out.println(loadedPerson.phoneNumbers.size()); // prints 1

我试着大声思考。比方说,在这两种情况下,我们都会急切地获取。对于第一种情况,其中PhoneNumber是拥有实体,我们将启动第一个查询以获取所有Person实体,然后启动每个Person的单独查询以获取该Person的所有PhoneNumber。然而,如果我们有Person作为拥有方,我们只需要使用连接触发一个查询。如果这是一个愚蠢的问题,我很抱歉,但是当Person是PhoneNumber中的FK时,连接不可能吗?是的,当Person id为FK时,连接也应该是可能的。在这里,我(假设)标准化查找会更快,但您必须查看您的解释计划才能确定。使用关系表的另一个原因(至少在理论上)是允许共享电话号码,比如两个人轮班使用的电话号码。坦白地说,ORM层的工作方式对于这些考虑应该是无关紧要的,因为没有人在设计模式时考虑ORM层。请看我在这篇文章中的答案,还有“mappedBy”和“owning side”的原因。如果我们不定义owning side,GOTCHAs,会发生什么-