Hibernate:脏数据检测和仅更新脏属性?

19
在“好老的JDBC时代”,我写了很多SQL代码,只更新实际更改的“属性/成员”:
例如,考虑一个具有以下成员的对象:
public String name;
public String address;
public Date date;
如果一个业务方法只更改了date,那么我只会针对date成员发出SQL UPDATE。然而,似乎(这是我的对Hibernate的“印象”),即使只更新单个成员,使用标准Hibernate映射(映射整个类)也会导致Hibernate在生成的SQL语句中完全更新该对象。
我的问题是:
1.这种观察是否正确,即Hibernate在完全映射的类中没有智能检查哪些成员已更改并仅为特定更改的成员发出更新,而总是将所有映射的成员(类)更新(如果对象由于一个成员脏而变脏...)
2.我该怎么做才能让Hibernate仅更新已更改的成员? 我正在寻找一种解决方案,使Hibernate仅更新实际更改的成员。(我知道Hibernate会对脏检查进行相当多的工作,但就我所知,这种脏检查只与识别整个对象是否脏有关,而不是哪个单独成员是脏的。)
4个回答

18

实际上,您可以在类映射中指定选项dynamic-updatedynamic-insert。它就是这样做的。更多信息请参见此处


嗨Maurice,非常感谢!!!你的帮助太有用了。我之前不知道"dynamic-update"这个功能,但在你的帮助下,我找到了相关资料并完全明白如何解决我的问题。非常非常感谢!!! - jens
1
现在 dynamic-update/dynamic-insert 已经被弃用,您可以使用 @DynamicUpdate/@DynamicInsert 代替。 - Abdelghani Roussi

5
Hibernate 只更新你真正想要更新的内容。
public class Person {

    private Integer id;

    public String name;
    public String address;
    public Date date;

    // getter's and setter's

}

然后你可以像这样做:

Person person = (Person) sessionFactory.openSession().get(Person.class, personId);

person.setName("jean");

Hibernate很聪明,它知道只有名称属性被更改了。虽然你可以看到以下日志:
UPDATE PERSON (NAME, ADDRESS, DATE) VALUES (?, ?, ?);

由于Hibernate为每个实体缓存每个SQL(INSERT、UPDATE、SELECT)查询,因此它只会更新您真正想要的内容。

你好Arthur,谢谢你的回答!“dynamic-update”关键字确实解决了我的问题。谢谢! - jens
@jens 你确定要使用动态查询吗?每次你动态更新实例时,Hibernate都需要创建一个新的更新查询,而不是使用缓存的更新查询。请注意性能问题。 - Arthur Ronald
1
谢谢您的回复。您当然是正确的。通常我不会使用动态更新。但是在一个“多并发”环境中,多个进程将更新记录/对象,但幸运的是,这些更新没有关联。进程A将始终更新列1、2,进程B将更新列3、4等。通过使用“动态更新”,我可以只更新1,2或3,4而没有任何问题。然而,如果我要更新所有列1,2,3,4的整个对象,我将不得不引入版本控制并处理失败的更新...总的来说,您是完全正确的。 - jens

2

0

我认为如果你的数据库负载很重并且需要在完整更新时重新创建一个或多个索引(包括那些未更改值的列),那么动态更新是不错的选择。

也许某些DBMS会识别如果UPDATE设置了已经存在的值,则不会更新包含该列的索引。但许多似乎太"愚蠢"以至于无法识别这一点(或者出于性能原因没有检查)。

对于大多数DB客户端应用程序来说,创建SQL查询的客户端负载不是问题。在DB中解释SQL所需的时间应该比重新创建大型索引要少。

如果我说错了,请纠正我!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接