更新实体,仅覆盖非空值(不进行动态查询)

时间:2019-05-12 17:11:34

标签: java hibernate jpa spring-data-jpa spring-data

我想通过将现有实体的“不完整”实例移交给JpaRepository来更新现有实体。不完整是指仅设置了要更改的值,而其他值是null。现在,如果我愿意这样做,所有null的值也将另存为null,因此将覆盖我想要保留的值。

我考虑过先从数据库加载实体,然后以某种方式将更改合并到该加载的对象中,然后再次保存,但是必须有更好的方法。

我的实体:

@Entity
@Table
public class Location {

    @Id
    @NotNull
    @Type(type = "uuid-char")
    private UUID id = UUID.randomUUID();

    @Column
    @NotEmpty
    private String title;

    @Column
    @NotEmpty
    private String description;
...

我的存储库:

@Repository
public interface LocationRepository extends JpaRepository<Location, UUID>, LocationFilterFragment, JpaSpecificationExecutor {

    Optional<Location> findLocationById(UUID id);
...

我顺便使用了标准的repo.save(location)方法。

更新:一种方法可能是使用动态查询/条件查询,但我正在寻找更方便,更不易出错的东西。

向我展示正确的方向就足够了,因为我不知道确切要寻找什么。预先感谢!

1 个答案:

答案 0 :(得分:1)

我的第一种方法是:不要合并您不完整的对象。如果您在存储库上调用save(在entityManager上转换为merge),则Hibernate会将其视为当前状态,并将更新所有值。

我将继续进行以下操作:

  • 通过id查找要更改的实体
  • 通过从“不完整的对象”中复制要设置的值来设置

请记住,这两个步骤必须在一个事务中执行。退出事务范围时,休眠将依赖其脏检查机制并更新实体(无需进行merge调用)。在这种方法中,“不完整的对象”不必是实体,它永远不会持久。 / p>

请注意,默认情况下,如果您只希望将脏字段作为查询的一部分,则所有字段都将在更新查询中发送(但现在未更改的字段不为空,它们反映了dB的先前状态),请了解@DynamicUpdate

另一注:如果您关闭了自定义jpql或标准API更新,则可以选择不执行一个选择。不利的一面是,Hibernate不了解所做的更改,也不会更新其缓存。