Hibernate:脏检查和只更新脏属性?

在“好老的JDBC时代”中,我编写了许多SQL代码,只对实际更改的“属性/成员”进行了非常有针对性的更新:

例如,考虑具有以下成员的对象:

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

如果在某些Business Method中只更改了date ,我只会为date成员发出SQL UPDATE

然而,似乎(这是我对Hibernate的“印象”)当使用标准Hibernate映射(映射完整类)时,即使只有单个成员的更新也会导致Hibernate生成的SQL语句中对象的完全更新。

我的问题是:

  1. 这个观察是否正确,Hibernate 不会智能地检查(在完全映射的类中),哪些成员发生了更改,然后只发布特定更改成员的更新,而是始终更新(在生成的SQL Update语句中)所有映射成员(类),即使它们没有被更改(如果对象因一个成员脏了而变脏…)

  2. 我该怎么做才能让Hibernate更新那些已被更改的成员? 我正在寻找一个解决方案让Hibernate只更新实际更改的成员。

(我知道Hibernate在脏检查方面做了很多工作,但据我所知,这个脏检查只与识别整个对象是否脏,而不是单个成员是脏的有关。)

实际上,您可以在类映射中指定选项dynamic-updatedynamic-insert 。 就是这样。 更多信息在这里 。

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)查询,它只是更新你真正想要的东西。

您可以通过实现CustomEntityDirtinessStrategy或Interceptor等接口来优化脏检查。 请参阅http://prismoskills.appspot.com/lessons/Hibernate/Chapter_20_-_Dirty_checking.jsp上的工作示例

我认为如果您有大量数据库负载和一个或多个索引在完整更新(其中所有列都更新,还有那些未更改的值)上重新创建,则动态更新很好。

也许某些DBMS会识别UPDATE是否将已存在的值设置为不更新包含该列的索引。 但是许多人似乎太“愚蠢”地认识到这一点(或者出于性能原因不进行检查)。

对于大多数数据库客户端应用程序,创建SQL查询的客户端负载不是问题。 在数据库中解释SQL应该比重新创建大索引花费更少的时间。

如果我错了请纠正我!