开发者

JPA/Hibernate preUpdate doesn't update parent object

开发者 https://www.devze.com 2023-04-12 14:20 出处:网络
In my application I defined following classes: @Entity @Table(name = \"forums\") public class Forum { @Id

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?


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号