Rav*_*per 6 java spring hibernate spring-data-jpa
我正在使用spring data-jpa。我只想更新一栏。
我的资料库是;
public interface UserRepository extends JpaRepository<User,Long> {
}
Run Code Online (Sandbox Code Playgroud)
我的服务是;
public User save(User user) {
return userRepository.save(user);
}
Run Code Online (Sandbox Code Playgroud)
我的实体;
@Entity
@DynamicUpdate(true)
public class User implements Serializable {
// column definitions, etc.
}
Run Code Online (Sandbox Code Playgroud)
如何只更新其中的一列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);
Run Code Online (Sandbox Code Playgroud)
第三种解决方案:
作为最后的解决方案,我建议您使用updatable = false。这将在实体插入的第一刻填充属性。
@Column(name = "create_date", nullable = false, updatable = false)
private Instant createDate;
Run Code Online (Sandbox Code Playgroud)
您的问题是由于您传递了一个全新的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);
}
Run Code Online (Sandbox Code Playgroud)
有了上面的逻辑,再加上动态更新注释,你应该只能看到 name 列的更新,除非你启用了一些审计,或者使用了@Version'ed 列。
如果更新的列总是相同的,那么最好将updatable = false其@Column用于定义中不是更新目标的列,因为使用@DynamicUpdate效率非常低,因为它重新生成每个 sql,从不使用缓存的 sql。但请注意使用此功能,因为您根本无法更新这些列。
我不建议使用,@Query除非您有原生 JPA/Hibernate 不足的情况,但如果您有一个仅更新目标列集的用例,它是最好的选择,也是最有效的。
如果更新的列有很多,可以极大地变化,要么限定之间的手动映射逻辑newUser到currentUser,或利用一些映射工具,如Orika,我有一个类似的自动化结构,其中数百实体通过这些映射器修补,允许一个非常通用的方法处理许多 CRUD 操作。
| 归档时间: |
|
| 查看次数: |
5456 次 |
| 最近记录: |