Как правильно использовать аудит mongodb с вложенными объектами аудита в поле типа коллекции - PullRequest
0 голосов
/ 22 апреля 2019

Я использую @EnableMongoAuditing и другие 4 аннотации (@LastModifiedDate ...) в моем проекте, они отлично работают, когда я использую только одну сущность, но ошибка произошла, когда непротестированные сущности

nested entities

Скажем, у меня есть структура данных этой сущности, EntityA и EntityB оба расширяют AbstractEntity (значит, имеют свои собственные поля аудита). У EntityA есть поле сбора, содержащее объекты EntityB.

Возникла исключительная ситуация java.lang.IllegalArgumentException при сохранении экземпляра EntityA в БД. Трассировка стека:

  at org.springframework.util.Assert.instanceCheckFailed(Assert.java:655)
  at org.springframework.util.Assert.isInstanceOf(Assert.java:574)
  at org.springframework.data.mapping.model.BasicPersistentEntity.verifyBeanType(BasicPersistentEntity.java:551)
  at org.springframework.data.mapping.model.BasicPersistentEntity.getPropertyAccessor(BasicPersistentEntity.java:453)
  at org.springframework.data.mapping.PersistentPropertyAccessor.setProperty(PersistentPropertyAccessor.java:76)
  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.lambda$setDateProperty$2(MappingAuditableBeanWrapperFactory.java:243)
  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper$$Lambda$1129.335811674.accept(Unknown Source:-1)
  at java.lang.Iterable.forEach(Iterable.java:75)
  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.setDateProperty(MappingAuditableBeanWrapperFactory.java:243)
  at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingMetadataAuditableBeanWrapper.setLastModifiedDate(MappingAuditableBeanWrapperFactory.java:220)
  at org.springframework.data.auditing.AuditingHandler.lambda$touchDate$11(AuditingHandler.java:220)
  at org.springframework.data.auditing.AuditingHandler$$Lambda$1128.164899054.accept(Unknown Source:-1)
  at java.util.Optional.ifPresent(Optional.java:159)
  at org.springframework.data.auditing.AuditingHandler.touchDate(AuditingHandler.java:220)
  at org.springframework.data.auditing.AuditingHandler.lambda$touch$0(AuditingHandler.java:166)
  at org.springframework.data.auditing.AuditingHandler$$Lambda$1122.754120807.apply(Unknown Source:-1)
  at java.util.Optional.map(Optional.java:215)
  at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:163)
  at org.springframework.data.auditing.AuditingHandler.markModified(AuditingHandler.java:143)
  at org.springframework.data.auditing.IsNewAwareAuditingHandler.markAudited(IsNewAwareAuditingHandler.java:83)
  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.lambda$onApplicationEvent$0(AuditingEventListener.java:54)
  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener$$Lambda$1094.1600079218.apply(Unknown Source:-1)
  at org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent.mapSource(MongoMappingEvent.java:90)
  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.onApplicationEvent(AuditingEventListener.java:54)
  at org.springframework.data.mongodb.core.mapping.event.AuditingEventListener.onApplicationEvent(AuditingEventListener.java:32)
  at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
  at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
  at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
  at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:398)
  at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:355)
  at org.springframework.data.mongodb.core.ReactiveMongoTemplate.maybeEmitEvent(ReactiveMongoTemplate.java:2407)
  at org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$doSave$35(ReactiveMongoTemplate.java:1428)
  at org.springframework.data.mongodb.core.ReactiveMongoTemplate$$Lambda$1093.1542796792.doInCollection(Unknown Source:-1)
  at org.springframework.data.mongodb.core.ReactiveMongoTemplate.lambda$createMono$8(ReactiveMongoTemplate.java:599)
  at org.springframework.data.mongodb.core.ReactiveMongoTemplate$$Lambda$989.249044352.apply(Unknown Source:-1)

Сообщение об ошибке: "Целевой компонент типа java.util.ArrayList не относится к типу постоянного объекта (EntityB) !: java.util.ArrayList"

Как правильно получить автоматический аудит EntityA (содержит коллекции EntityB)?


выводы:

когда PersistentPropertyAccessor устанавливает свойство для каждого аннотированного поля, и это поле имеет тип коллекции, код из setProperty кажется неправильным:

Object parent = parentPath.isEmpty() ? getBean() : getProperty(parentPath);//1

        if (parent == null) {

            String nullIntermediateMessage = "Cannot lookup property %s on null intermediate! Original path was: %s on %s.";

            throw new MappingException(String.format(nullIntermediateMessage, parentPath.getLeafProperty(), path.toDotPath(),
                    getBean().getClass().getName()));
        }

        PersistentPropertyAccessor<?> accessor = parent == getBean() //
                ? this //
                : leafProperty.getOwner().getPropertyAccessor(parent);//2

1.Скажите, что «entityA.entityB» parentPath не пустой и имеет тип коллекции, поэтому параметр parent становится коллекцией.

2. Должны ли здесь итерироваться родительский элемент и метод getPropertyAccessor для каждого элемента?

...