如何使用Hibernate仅更新实体属性的一部分

9

我收到了一个有30个字段的JSON,我的实体是从这个JSON构建出来的。

问题是:两个字段不应该被更新(即两个日期字段)。

如果使用entity.merge,那么这两个字段都会被更新。

有什么方法可以避免这两个字段被更新吗?

也许可以使用criterion.Example吗?

是否有一些方法可以不用写大量的HQL来实现呢?

2个回答

17

如果您不想更新这两个字段,可以使用 @Column(updatable=false) 进行标记:

@Column(name="CREATED_ON", updatable=false)
private Date createdOn;

一旦你加载了一个实体并对其进行修改,在当前的SessionEntityManager仍然开启的情况下,Hibernate可以通过脏数据检查机制跟踪这些更改。然后,在flush期间,将执行一个SQL更新。

如果您不想在UPDATE语句中包含所有列,可以使用动态更新:

@Entity
@DynamicUpdate
public class Product {
   //code omitted for brevity
}

然后,只有被修改的列会被包含在UPDATE语句中。


你能否详细说明一下 @SelectBeforeUpdate (https://docs.jboss.org/hibernate/orm/5.2/javadocs/org/hibernate/annotations/SelectBeforeUpdate.html)?因为 @DynamicUpdate 确实只更新已更改的列,但当我的实体包含 5 个外键并更新时,它会选择所有这些关系,即使它们没有更改。我想摆脱这些不必要的查询和更新。对我来说,@SelectBeforeUpdate(false) 的工作方式并非我所认为的那样。 - Robert Niestroj

0
像这个例子一样做:
    public class UpdateMethodDemo {
        public static void main(String[] args) {
            Session session = HibernateUtil.getSessionFactory().openSession();
            Student s = studentService.getById(1);
            s.setNom("FuSsA");
            session.beginTransaction();
            session.update(s);
            session.getTransaction().commit();
            session.close();
        }

} 

编辑:

您可以使用@Transient注释来表示该字段不会被持久化到数据库中。


谢谢。我知道这是一种选择,但也许有更简单的方法。 - Bruno Campos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接