繁体   English   中英

如何在弹簧数据jpa中使用hibernate @DynamicUpdate?

[英]How to use hibernate @DynamicUpdate with spring data jpa?

我正在使用spring data-jpa。 我想只更新一列。

我的存储库是;

public interface UserRepository extends JpaRepository<User,Long> {
}

我的服务是;

public User save(User user) {
    return userRepository.save(user);
}

我的实体;

@Entity
@DynamicUpdate(true)
public class User implements Serializable {
    // column definitions, etc.
}

如何仅更新User一列?

首先,我想解释为什么@DynamicUpdate不适合你。 所以我应该注意@DynamicUpdate是如何工作的:

@DynamicUpdate注释用于指定每当修改实体时都应生成UPDATE SQL语句。 默认情况下,Hibernate使用缓存的UPDATE语句来设置所有表列。 使用@DynamicUpdate批注对实体进行批注时,PreparedStatement将仅包含其值已更改的列。( 更多详细信息

例如,假设User有一个名为name的属性。

因此,如果您第一次使用已定义的名称保存用户,则现在传递null因为值@DynamicUpdate将其视为更改并尝试将名称更新为null

第一解决方案

作为第一个解决方案,如果您希望@DynamicUpdate工作,首先应该用旧值填充所有其他User属性,然后您可以保存它。

优点:生成的SQL查询只是更新所需的属性。

缺点: Hibernate每次都必须生成相应的SQL字符串,因此Hibernate方面会产生性能成本。

二解决方案:

您可以使用自定义查询更新User

@Modifying
@Query("UPDATE User SET name=(:name) WHERE id=(:id)")
public void updateName(@Param("name")String name, @Param("id")Long id);

第三种方案:

作为最后的解决方案,我建议你使用updatable = false 这将在实体插入的第一时刻填充该属性。

  @Column(name = "create_date", nullable = false, updatable = false)
    private Instant createDate;

您的问题是由于您传递了一个全新的User实体,因此Hibernate无法使用已经从数据库中获取的缓存版本并决定动态更新哪些列。

因此,请尝试执行以下操作以确认@DynamicUpdate的正确行为;

在职;

@Transactional
public User save(User newUser) {
    User currentUser = userRepository.get(newUser.getId());
    // handle merging of updated columns onto currentUser manually or via some mapping tool
    currentUser.setName(newUser.getName());
    return userRepository.save(currentUser);
}

使用上述逻辑以及动态更新注释,您应该能够看到仅更新名称列,除非您启用了某些审核,或使用@Version的ed列。

如果更新的列总是相同的,那么最好对那些不是@Column定义中的更新目标的列使用updatable = false ,因为使用@DynamicUpdate是非常低效的,因为它重新生成每个sql,从不使用缓存sql语句。 但请注意使用此功能,因为您根本无法更新这些列。

我建议不要使用@Query除非你有一个本机JPA / Hibernate不足的情况,但如果你有一个用例来更新目标列集,那么它是最好的选择,也是最有效的。

如果更新的列很多且变化很大,要么在newUsercurrentUser之间定义手动映射逻辑,要么利用一些映射工具(如Orika ,我有一个类似的自动化结构,通过这些映射器修补数百个实体,允许非常通用的方法来处理许多CRUD操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM