问题 JPA2.0 / Hibernate:为什么JPA会激活查询以更新所有列值,甚至托管bean的某些状态也会更改?


我正在使用JPA2.0和Hibernate。

例如,我有下表的JPA实体:

User [userId, userName, userAddress]

我可以使用find()方法获取用户实体:

User user = entityManager.find(User.class , 1L); // 1L is user id

现在,如果我在上面提取的同一个用户实体上更改任何用户的状态(比如说userName):

user.setUserName("Narendra");

并使用merge()方法执行合并:

entityManager.merge(user);

使用JPA / hibernate在合并时触发的以下查询成功执行合并:

Hibernate: update User set USERID =?, USERNAME=?, USERADDRESS=? where USERID=?

在这里我的问题是,如果我在User实体中仅更改了用户名状态,我没有更改userId,userAddress等.JPA应该在查询之下(仅更改userName)而不是查询之上。

 Hibernate: update User set USERNAME=? where USERID=?

有什么想法吗?


1052
2018-04-02 09:44


起源



答案:


看看 dynamic-update 属性。

dynamic-update(可选 - 默认为false):指定应在运行时生成UPDATE SQL,并且只能包含值已更改的列。

考虑到动态更新可能会对性能产生一些影响。使用它有一点开销,如果你没有一个包含大量不太可能被修改的列的大型(可能是遗留的)表,它可能会适得其反。看到这个相关的问题 Hibernate:动态更新动态插入 - 性能效果

Hibernate <4.0

如果您正在使用Hibernate Annotations,请使用特定于Hibernate的 @Entity 注释与 JPA 一:

@org.hibernate.annotations.Entity(dynamicUpdate = true)

如果您正在使用XML映射:

<class name="User" table="user" dynamic-update="true">

休眠> = 4.0

特定于Hibernate的@Entity注释已在Hibernate 4.0中弃用,并计划在4.1中消失。使用动态更新的正确方法是使用注释实体 @DynamicUpdate 现在(感谢@Tiny的抬头)。


10
2018-04-02 09:48



谢谢回复。这个解决方案我试过并且工作正常。但是,我担心在所有被定义为JPA entites的entites中添加hibernate特定属性。有没有办法在persistence.xml中配置一些东西,以便可以使用此配置插入每个实体? - Narendra Verma
有一个有趣的问题与这个相同的主题相关: Hibernate JPA如何在persistence.xml中配置dynamic-update。无法在中定义此行为 persistence.xml,因为它是特定于Hibernate的。也许您可以尝试使用特定的hibernate-config文件 persistence.xml,或者在启动监听器中使用某种运行时字节码操作来添加Hibernate @Entity 运行时对所有映射类的注释。并记住接受你的问题的正确答案。 - Xavi López
是的,我有了主意。最后但同样重要的是,我接受了你的回答。谢谢 - Narendra Verma
@Tiny谢谢,在答案上添加了一个注释(也谢谢你说,我还没有意识到:-) - Xavi López


答案:


看看 dynamic-update 属性。

dynamic-update(可选 - 默认为false):指定应在运行时生成UPDATE SQL,并且只能包含值已更改的列。

考虑到动态更新可能会对性能产生一些影响。使用它有一点开销,如果你没有一个包含大量不太可能被修改的列的大型(可能是遗留的)表,它可能会适得其反。看到这个相关的问题 Hibernate:动态更新动态插入 - 性能效果

Hibernate <4.0

如果您正在使用Hibernate Annotations,请使用特定于Hibernate的 @Entity 注释与 JPA 一:

@org.hibernate.annotations.Entity(dynamicUpdate = true)

如果您正在使用XML映射:

<class name="User" table="user" dynamic-update="true">

休眠> = 4.0

特定于Hibernate的@Entity注释已在Hibernate 4.0中弃用,并计划在4.1中消失。使用动态更新的正确方法是使用注释实体 @DynamicUpdate 现在(感谢@Tiny的抬头)。


10
2018-04-02 09:48



谢谢回复。这个解决方案我试过并且工作正常。但是,我担心在所有被定义为JPA entites的entites中添加hibernate特定属性。有没有办法在persistence.xml中配置一些东西,以便可以使用此配置插入每个实体? - Narendra Verma
有一个有趣的问题与这个相同的主题相关: Hibernate JPA如何在persistence.xml中配置dynamic-update。无法在中定义此行为 persistence.xml,因为它是特定于Hibernate的。也许您可以尝试使用特定的hibernate-config文件 persistence.xml,或者在启动监听器中使用某种运行时字节码操作来添加Hibernate @Entity 运行时对所有映射类的注释。并记住接受你的问题的正确答案。 - Xavi López
是的,我有了主意。最后但同样重要的是,我接受了你的回答。谢谢 - Narendra Verma
@Tiny谢谢,在答案上添加了一个注释(也谢谢你说,我还没有意识到:-) - Xavi López


也可以用作注释:

import org.hibernate.annotations.DynamicUpdate;

@Entity
@DynamicUpdate
@Table(name = "payments")
public class Payment {
    ...
}

1
2017-11-09 06:28