2010-04-20 61 views
14

在“良好的旧JDBC时代”中,我写了很多SQL代码,它们仅对实际更改的“属性/成员”进行了非常有针对性的更新:休眠:脏检查和只更新脏属性?

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

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

如果只有date在一些商业方法的改变,我只会发出的date成员的SQL UPDATE。然而

看来(这是我的Hibernate的“印象”),与标准的Hibernate映射工作时(映射满级),甚至只有一个成员牵头的更新对象的完全更新的SQL语句由Hibernate生成。

我的问题是:

  1. 这是观察是正确的,即休眠智能检查(在完全映射类),有什么地方改变了,然后只发出更新成员(们)但是总是会更新(在生成的SQL更新语句中)所有映射成员(类的成员),即使它们没有被更改(如果对象由于一个成员很脏而变脏)...

  2. 我该怎么做才能让Hibernate只更新这些成员,th已经改变了?我正在寻找一种解决方案,让Hibernate只更新实际更改的成员。

(我知道Hibernate并不脏检查相当一些工作,但据我所知,这个肮脏的检查是唯一相关,以确定如果对象作为一个整体是脏的,而不是单一的部件脏了。)

回答

13

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

+0

你好Maurice,非常感谢你!你的帮助是绝对有用的。我没有意识到“动态更新”功能,在您的帮助下我可以谷歌,现在我完全知道如何解决我的问题。非常感谢! – jens 2010-04-21 07:15:52

+1

现在动态更新/动态插入已弃用,因此您可以使用@ DynamicUpdate/@ DynamicInsert代替 – 2015-08-13 20:30:38

4

休眠只需更新你真的想

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)查询每一个实体,再次,它只是更新你真正想。

+0

您好亚瑟,谢谢您的回答! “动态更新”关键字真的解决了我的问题。谢谢 ! – jens 2010-04-21 07:17:58

+0

@jens你确定要使用动态查询?每次你*动态更新你的实例时,Hibernate都需要创建一个新的更新查询*而不是使用缓存更新查询*。注意性能问题。 – 2010-04-21 14:54:08

+1

感谢您的回复。你当然是对的。通常我不会使用动态的。但是在“多并发”环境中,我有一个非常特殊的要求,其中多个进程将更新记录/对象。但对我的运气来说,后者并不相关。进程A将总是upate列1,2和进程B将更新列3,4等...通过使用“动态更新”我只能更新1,2或3,4没有任何问题。但是,当我用所有列1,2,3,4更新整个对象时,我将不得不引入版本控制并处理失败的更新......一般而言,您是绝对正确的。 – jens 2010-04-21 18:10:21

0

我认为动态更新是很好,如果你有一个完整的更新(所有列都更新,还有那些值不变)重载数据库和一个或多个索引重新创建。

也许某些DBMS可以识别UPDATE是否设置一个已经存在的值来不更新包含该列的索引。但很多人认为这太“愚蠢”了(或者出于性能原因不检查)。

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

如果我错了,请纠正我!