Java 当子实体发生更改时,如何更新根实体上已修改的_at列?

Java 当子实体发生更改时,如何更新根实体上已修改的_at列?,java,spring,hibernate,Java,Spring,Hibernate,当子实体发生更改时,是否有方法告诉hibernate在根实体的列中更改modified\u? 我有60多个数据库表。有一个根实体。每当我更改任何表时,我都需要将该更改传播到根实体,并在列中更新modified\u。级联以另一种方式根->子级工作。我需要child->root。解决此问题的最佳方法是什么?有什么建议吗?我读过关于事件侦听器的内容,但我发现它对于我的用例来说太复杂了。我想不出更优雅、更容易实现的东西。有什么建议吗?我是在受启发的事件监听器中做的。我创建了两个侦听器,一个用于插入,另一

当子实体发生更改时,是否有方法告诉hibernate在根实体的列中更改
modified\u?


我有60多个数据库表。有一个根实体。每当我更改任何表时,我都需要将该更改传播到根实体,并在
列中更新
modified\u。
级联
以另一种方式根->子级工作。我需要child->root。

解决此问题的最佳方法是什么?有什么建议吗?我读过关于
事件侦听器的内容,但我发现它对于我的用例来说太复杂了。我想不出更优雅、更容易实现的东西。有什么建议吗?

我是在受启发的
事件监听器中做的。我创建了两个侦听器,一个用于插入,另一个用于更新/删除。它们拦截更改,每当发生更改时,我都会在根实体的
列中更新
modified\u

@Component
public class RootAwareInsertEventListener implements PersistEventListener {

    private static final Logger logger = LoggerFactory.getLogger(RootAwareInsertEventListener.class);

    @Autowired
    private EntityManagerFactory emf;

    @PostConstruct
    private void init() {
        SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class);
        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
        registry.getEventListenerGroup(EventType.PERSIST).appendListener(this);
    }

    /**
     * Intercept hibernate persist - and if entity is RootAware it will update modified_at of root entity
     */
    @Override
    public void onPersist(PersistEvent event) throws HibernateException {
        final Object entity = event.getObject();

        if (entity instanceof RootAware) {
            RootAware rootAware = (RootAware) entity;
            MortgageCase root = (MortgageCase) rootAware.root();
            logger.info("Modifing {} modified_at because a {} child entity has been inserted", root, entity);
            root.setModifiedAt(new Date());
        }
    }

    @Override
    public void onPersist(PersistEvent event, Map createdAlready) throws HibernateException {
        onPersist(event);
    }
}

@Component
public class RootAwareUpdateAndDeleteEventListener implements FlushEntityEventListener {

    private static final Logger logger = LoggerFactory.getLogger(RootAwareUpdateAndDeleteEventListener.class);

    @Autowired
    private EntityManagerFactory emf;

    @PostConstruct
    private void init() {
        SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class);
        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
        registry.getEventListenerGroup(EventType.FLUSH_ENTITY).appendListener(this);
    }

    /**
     * Intercept hibernate update / delete - and if entity is RootAware it will update modified_at of root entity
     */
    @Override
    public void onFlushEntity(FlushEntityEvent event) throws HibernateException {
        final EntityEntry entry = event.getEntityEntry();
        final Object entity = event.getEntity();
        final boolean mightBeDirty = entry.requiresDirtyCheck(entity);

        if (mightBeDirty && entity instanceof RootAware) {
            RootAware rootAware = (RootAware) entity;
            if (updated(event)) {
                MortgageCase root = (MortgageCase) rootAware.root();
                logger.info("Modifing {} modified_at because a {} child entity has been updated", root, entity);
                root.setModifiedAt(new Date());
            } else if (deleted(event)) {
                MortgageCase root = (MortgageCase) rootAware.root();
                logger.info("Modifing {} modified_at because a {} child entity has been deleted", root, entity);
                root.setModifiedAt(new Date());
            }
        }
    }

    private boolean deleted(FlushEntityEvent event) {
        return event.getEntityEntry().getStatus() == Status.DELETED;
    }

    private boolean updated(FlushEntityEvent event) {
        final EntityEntry entry = event.getEntityEntry();
        final Object entity = event.getEntity();

        int[] dirtyProperties;
        EntityPersister persister = entry.getPersister();
        final Object[] values = event.getPropertyValues();
        SessionImplementor session = event.getSession();

        if (event.hasDatabaseSnapshot()) {
            dirtyProperties = persister.findModified(event.getDatabaseSnapshot(), values, entity, session);
        } else {
            dirtyProperties = persister.findDirty(values, entry.getLoadedState(), entity, session);
        }

        return dirtyProperties != null;
    }
}