JPA/Hibernate preUpdate doesn't update parent object

旧城冷巷雨未停 提交于 2019-12-09 00:57:47

问题


In my application I defined following classes:

@Entity
@Table(name = "forums")
public class Forum {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private String id;

    private String name;
    private Date lastActivity;

    @OneToMany(mappedBy = "forum", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
    private List<Post> posts;

@Entity
@Table(name = "posts")
public class Post {
    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    private String id;

    private String username;
    private String content;
    private Date creationDate;

    @ManyToOne(optional = false, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
    private Forum forum;

    public Post() {
        creationDate = new Date();
    }

    @PrePersist
    private void onPersist() {
        System.out.println(getClass().getName() + ": onPersist");
        if (creationDate == null) {
            creationDate = new Date();
        }

        forum.setLastActivity(creationDate);
    }

    @PreUpdate
    private void onUpdate() {
        forum.setLastActivity(new Date());
    }

If I try adding new posts to forum entity, lastActivity field is correctly updated in database by @PrePersist callback. But if I try to update post entity using following code:

  entityManager.getTransaction().begin();
  Post post = entityManager.find(Post.class, "postId");
  post.setContent("New post text");
  entityManager.merge(post);
  entityManager.getTransaction().commit();

only post data are updated and lastActivity field value doesn't change. In my opinion @PreUpdate method should do the trick and update Forum entity. Is this a bug or am I missing something?


回答1:


It is not bug, even that with a fast try this worked for me way you expected. Negative news is that it is not guaranteed to work, because of:

From page 93 in JPA 2.0 specification:

In general, the lifecycle method of a portable application should not invoke EntityManager or Query operations, access other entity instances, or modify relationships within the same persistence context.[43] A lifecycle callback method may modify the non-relationship state of the entity on which it is invoked.

And page 95:

It is implementation-dependent as to whether callback methods are invoked before or after the cascading of the lifecycle events to related entities. Applications should not depend on this ordering.




回答2:


post.merge() has no use here. post is clearly attached to the session already.

Make sure you've got the content attribute mapped to a column, if it is not, Hibernate has no way of telling if the entity is dirty, and therefore flush the changes to the DB.



来源:https://stackoverflow.com/questions/7753702/jpa-hibernate-preupdate-doesnt-update-parent-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!