有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java通过EventListener更新Hibernate实体

在将实体写入数据库之前,我在Hibernate中使用PreInsert和PreUpdate EventListeners设置“创建”和“更新”时间戳的值。问题是下次Hibernate读取然后刷新实体时,Hibernate看到更改的时间戳并认为即使没有其他更改,也需要更新对象。所以监听器再次被激发,更新发生,并且一遍又一遍地重复

理想情况下,我希望能够分配这些时间戳,而不会在下次刷新时休眠认为对象脏了。处理此问题的最佳解决方案是什么?我想我可以撤销这张肮脏支票,但我想看看其他人怎么做

以下是一些示例代码供参考(这只是示例代码,无需吹毛求疵):

@Entity
class MyEntity {
    @Id
    Long id = Long.valueOf(1);
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;
    @Temporal(TemporalType.TIMESTAMP)
    private Date updated;

    @Override
    public void setCreated(Date created) {
        this.created = created;
    }

    @Override
    public void setUpdated(Date updated) {
        this.updated = updated;
    }
}

public class PreInsertAndUpdateEventListener implements PreInsertEventListener, PreUpdateEventListener {
    @Override
    public boolean onPreUpdate(PreUpdateEvent event) {
        MyEntity.class.cast(event.getEntity()).setUpdated(new Date());
        return false;
    }

    @Override
    public boolean onPreInsert(PreInsertEvent event) {
        MyEntity.class.cast(event.getEntity()).setCreated(new Date());
        return false;
    }
}

public void updatedTest() {
    Session session = sessionFactory.openSession();
    Transaction t = session.beginTransaction();

    MyEntity p = new MyEntity();
    Serializable id = session.save(p);
    session.flush();

    for (int i = 0; i < 5; i++) {
        p = (MyEntity) session.get(MyEntity.class, id);
        session.update(p);
        session.flush(); // Update always fires here
    }

    t.commit();
    session.close();
}

共 (1) 个答案

  1. # 1 楼答案

    我决定采取的解决方案是,每次通过事件侦听器修改实体时,更新Hibernate的状态以匹配实体的状态。实现如下所示:

    StandardProperty[] properties = event.getPersister().getEntityMetamodel().getProperties();
    Object[] state = event.getState();
    
    for (int i = 0; i < properties.length; i++) {
        if (properties[i].getName().equals("updated")) {
            state[i] = timestamp;
            break;
        }
    }