JaversException: NOT_INSTANCE_OF: ошибка начальной загрузки JaVers - ожидаемый экземпляр «File», полученный экземпляр «com.mycompany.model.File» - PullRequest
0 голосов
/ 06 декабря 2018

Проблема:

Я интегрировал JaVers с существующим приложением Spring Boot, и хотя он работал как чудо, я столкнулся с этим исключением при попытке использовать @TypeNameаннотация при создании новой File сущности.

org.javers.common.exception.JaversException: NOT_INSTANCE_OF: JaVers bootstrap error - expected instance of 'File', got instance of 'com.mycompany.model.File'
    at org.javers.core.metamodel.type.EntityType.getIdOf(EntityType.java:76)
    at org.javers.core.metamodel.type.EntityType.createIdFromInstance(EntityType.java:87)
    at org.javers.core.metamodel.object.GlobalIdFactory.createId(GlobalIdFactory.java:57)
    at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:29)
    at org.javers.core.graph.LiveCdoFactory.create(LiveCdoFactory.java:15)
    at org.javers.core.graph.ObjectGraphBuilder.buildGraph(ObjectGraphBuilder.java:44)
    at org.javers.core.graph.LiveGraphFactory.createLiveGraph(LiveGraphFactory.java:39)
    at org.javers.core.commit.CommitFactory.createLiveGraph(CommitFactory.java:96)
    at org.javers.core.commit.CommitFactory.create(CommitFactory.java:75)
    at org.javers.core.JaversCore.commit(JaversCore.java:82)
    at org.javers.spring.jpa.JaversTransactionalDecorator.commit(JaversTransactionalDecorator.java:83)
    at org.javers.spring.jpa.JaversTransactionalDecorator$$FastClassBySpringCGLIB$$acb40bd0.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at org.javers.spring.jpa.JaversTransactionalDecorator$$EnhancerBySpringCGLIB$$3ab81589.commit(<generated>)
    at org.javers.spring.auditable.aspect.springdata.AbstractSpringAuditableRepositoryAspect.lambda$new$0(AbstractSpringAuditableRepositoryAspect.java:33)
    at org.javers.spring.auditable.aspect.springdata.AbstractSpringAuditableRepositoryAspect.lambda$onVersionEvent$3(AbstractSpringAuditableRepositoryAspect.java:52)
    at java.util.Optional.ifPresent(Optional.java:159)
    at org.javers.spring.auditable.aspect.springdata.AbstractSpringAuditableRepositoryAspect.onVersionEvent(AbstractSpringAuditableRepositoryAspect.java:48)
    at org.javers.spring.auditable.aspect.springdata.AbstractSpringAuditableRepositoryAspect.onSave(AbstractSpringAuditableRepositoryAspect.java:38)
    at org.javers.spring.auditable.aspect.springdatajpa.JaversSpringDataJpaAuditableRepositoryAspect.onSaveAndFlushExecuted(JaversSpringDataJpaAuditableRepositoryAspect.java:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644)
    at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:626)
    at org.springframework.aop.aspectj.AspectJAfterReturningAdvice.afterReturning(AspectJAfterReturningAdvice.java:66)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:56)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:174)
    at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:55)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:174)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
    at com.sun.proxy.$Proxy196.saveAndFlush(Unknown Source)
    at com.mycompany.service.FileServiceImpl.createRecord(FileServiceImpl.java:88)

Кажется, что по какой-то причине метод org.javers.core.metamodel.type.EntityType.getIdOf(EntityType.java:76) не использует @TypeName для определения типа экземпляра:

public Object getIdOf(Object instance) {
        Validate.argumentIsNotNull(instance);

        if (!isInstance(instance)) {
            throw new JaversException(JaversExceptionCode.NOT_INSTANCE_OF, getName(), instance.getClass().getName());
        }

        Object cdoId = getIdProperty().get(instance);
        if (cdoId == null) {
            throw new JaversException(JaversExceptionCode.ENTITY_INSTANCE_WITH_NULL_ID, getName(), getIdProperty().getName());
        }
        return cdoId;
    }

Чего мне не хватает?

Настройка:

Если я напечатаю MappingEntityType, я получу следующее:

Без аннотация @TypeName:

Type MappingEntityType{
  baseType: class com.mycompany.model.File
  typeName: com.mycompany.model.File
  managedProperties:
    Field Integer id; //declared in File
    Field String name; //declared in File
    Field byte[] data; //declared in File
    Field String mimeType; //declared in File
    Field Product product; //declared in File
  idProperty: id
}

С аннотацией :

Type MappingEntityType{
  baseType: class com.mycompany.model.File
  typeName: File
  managedProperties:
    Field Integer id; //declared in File
    Field String name; //declared in File
    Field byte[] data; //declared in File
    Field String mimeType; //declared in File
    Field Product product; //declared in File
  idProperty: id
}

Таким образом, сопоставление выглядит корректным, поскольку baseTypeто же самое, но typeName отличается.

My File Сущность определяется следующим образом:

@TypeName("File")
@Entity
@Table(name = "file")
public class File implements Model {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false, unique = true)
    private Integer id;

    @Column(name = "name", nullable = false, length = 50)
    private String name;

    @Lob
    @Column(name = "data", nullable = true)
    private byte[] data;

    @Column(name = "mime_type", nullable = true, length = 50)
    private String mimeType;

    @JoinColumn(name = "product_id", nullable = false)
    @ManyToOne(fetch = FetchType.LAZY)
    private Product product;
}

Примечание. Я использую HibernateUnproxyObjectAccessHook, поэтому, если я правильно понимаю ленивую загрузкуиз Product не должно быть проблемой.

...