【问题标题】:Hibernate: Dirty Checking and Only Update of Dirty Attributes?Hibernate:脏检查和只更新脏属性?
【发布时间】:2011-02-10 02:20:39
【问题描述】:

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

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

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

如果仅在某些业务方法中更改了 date,我只会为 date 成员发出 SQL UPDATE

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

我的问题是:

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

  2. 如何使 Hibernate 只更新那些已更改的成员?我正在寻找一种解决方案,让 Hibernate 只更新实际更改的成员。

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

【问题讨论】:

    标签: java hibernate


    【解决方案1】:

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

    【讨论】:

    • 你好莫里斯,非常感谢!!!你的帮助绝对有帮助。我不知道“动态更新”功能,在你的帮助下,我可以用谷歌搜索它,现在我绝对知道如何解决我的问题。非常非常感谢!!!
    • 现在动态更新/动态插入已被弃用,因此您可以改用@DynamicUpdate/@DynamicInsert
    【解决方案2】:

    休眠只需更新您真正想要的内容

    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 足够聪明,只知道 name 属性已更改。虽然你可以看到你的日志如下

    UPDATE PERSON (NAME, ADDRESS, DATE) VALUES (?, ?, ?);
    

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

    【讨论】:

    • 你好亚瑟,也谢谢你的回答!! “动态更新”关键字确实解决了我的问题。谢谢!
    • @jens 你确定要使用动态查询吗?每次动态更新实例时,Hibernate 都需要创建一个新的更新查询而不是使用缓存的更新查询。注意性能问题。
    • 感谢您的回复。你当然是对的。通常我不会使用动态更新。但是我在“多并发”环境中有一个非常特殊的要求,其中多个进程将更新记录/对象。但幸运的是,这些更新并不相关。进程 A 将始终更新 1,2 列,进程 B 将更新 3,4 列等...通过使用“动态更新”,我只能更新 1,2 或 3,4 没有任何问题。但是,当我使用所有 1、2、3、4 列更新整个对象时,我将不得不引入版本控制并处理失败的更新......一般来说你是绝对正确的。
    【解决方案3】:

    我认为,如果您的数据库负载很重,并且需要在完全更新时重新创建一个或多个索引(其中所有列都更新,值不变的列),那么动态更新会很好。

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

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

    如果我错了,请纠正我!

    【讨论】:

      【解决方案4】:

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

      的工作示例

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多