Как обновить столбецified_at в корневой сущности при изменении дочернего элемента? - PullRequest
0 голосов
/ 23 октября 2019

Есть ли способ сообщить hibernate об изменении столбца modified_at корневого объекта при каждом изменении дочернего объекта? У меня более 60 таблиц базы данных. Существует одна корневая сущность. Всякий раз, когда я изменяю какую-либо таблицу, мне нужно распространить это изменение на корневую сущность и обновить столбец modified_at. Cascades работает в обратном направлении root -> child. Мне нужен ребенок -> корень. Как лучше всего подойти к этой проблеме? Любые предложения? Я прочитал о Event Listeners, но считаю, что это слишком сложно для моего варианта использования. Я не мог придумать что-то более элегантное, более простое в реализации. Есть предложения как подойти?

1 Ответ

0 голосов
/ 24 октября 2019

Я сделал это, используя Event Listeners, вдохновленный этой статьей . Я создал 2 слушателя один для вставки и один для обновления / удаления. Они перехватывают изменения, и всякий раз, когда происходят изменения, я обновляю столбец modified_at корневого объекта.

@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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...