假设我有一个House实体,它映射到许多Person实体。然后我加载一个有20个占用者的现有房子。
beginTransaction();
House house = houseDao.find(1L);
commitTransaction();
稍后在代码中,我可以向众议院添加一个新人:
...
List<Person> people = house.getPeople();
people.add(new Person("Dilbert"));
....
当我拨打电话时:
session.saveOrUpdate(house);
Hibernate执行21次查询:1次选择House,20次选择House中的每个现有人员。
我确信这对我来说是一个小问题,但是,在这种情况下,我应该怎么做才能在房子里添加一个新人,而不会对数据库产生如此大的打击?
这都是在同一个会话中完成的。
答案 0 :(得分:3)
因为你真的没有给出很多对象的定义,所以我会做一些假设。
确保房屋的定义如下:
@Entity
public class House implements Serializable {
@Id
private int id;
@OneToMany(mappedBy="house")
private Set<Person> people;
... rest of your class
}
@Entity
public class Person implements Serializable {
@Id
private int id;
@ManyToOne(targetEntity=House.class)
private House house;
@Column(name="person_name")
private String name
... rest of your class
public Person(House house, String name) {
this.house = house;
this.name = name;
}
}
现在你的代码:
beginTransaction();
House house = houseDao.find(1L);
commitTransaction()
... your magic
Person person = new Person(house,"Dilbert");
session.saveOrUpdate(person);
在上面的示例中,当您使用父/子关系时(无关紧要,它是一对多或多对多),您可以通过子关系建立关系。我通常不会通过父母进行全面更新。在你的例子中,你会看到很多头脑。当你开始工作的地方有成千上万的记录时,它就变得不可能了。
根据您的模型,要研究的另一件事是对列表的注释进行细微更改。一个例子:
@Entity
public class House implements Serializable {
@Id
private int id;
@OneToMany(mappedBy="house")
@Fetch(FetchMode.JOIN)
private Set<Person> people;
... rest of your class
}
鉴于@Fetch不是JPA规范的一部分,而是一个hibernate注释,这取决于你的模型可以提供很大的性能提升,因为它会在单个查询中抓住house对象和所有人。如果您限制属于房屋的房屋和人数,这非常有效。如果你得到非常大的结果集,这可能不是一个好的情况。下一个例子可能更合适:
@Entity
public class House implements Serializable {
@Id
private int id;
@OneToMany(mappedBy="house")
@Fetch(FetchMode.SUBSELECT)
private Set<Person> people;
... rest of your class
}
这将使用两个查询来获取所有对象。对House对象的一个查询(或根据查询乘以house对象)和对于house对象的所有人的一个查询。
答案 1 :(得分:0)
我认为这是你问题的潜在答案,但也许不是你想的那样。
我还没有找到一种让Hibernate按照你想要的方式运行的方法(它没有那种级别的粒度)。如果你愿意,我相信你可以自己编码。但如果您真的担心数据库的性能损失,请解决问题并专注于如何最大限度地减少数据库上的负载。
优化从Hibernate到DB的调用的最佳方法是确保所有的hibernate对象表都被编入索引。 Hibernate使用父对象的主键调用表。这20个查询如果达到索引并且位置很快,则占用的处理时间非常短。 DB是为处理大量这样的事务而构建的 - 昂贵的部分是将数据定位在磁盘上并加载它以供您使用。
最后,我还要添加一个对象缓存。这可能会消除数据库的往返,从而为程序节省大量的I / O等待时间。