![](/img/trans.png)
[英]HIbernate @DynamicUpdate not working with JPA Entitymanager
[英]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不足的情况,但如果你有一个用例来更新目标列集,那么它是最好的选择,也是最有效的。
如果更新的列很多且变化很大,要么在newUser
和currentUser
之间定义手动映射逻辑,要么利用一些映射工具(如Orika
,我有一个类似的自动化结构,通过这些映射器修补数百个实体,允许非常通用的方法来处理许多CRUD操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.