Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MappingException when persisting Entity that implements Collection [DATACMNS-1458] #1889

Open
spring-projects-issues opened this issue Dec 28, 2018 · 0 comments
Assignees
Labels
in: mapping type: bug

Comments

@spring-projects-issues
Copy link

spring-projects-issues commented Dec 28, 2018

Michael A. Damone opened DATACMNS-1458 and commented

When trying to persist an Entity, using EntityManager.persist(Object), if that Entity also implements java.util.Collection then an exception is thrown:

org.springframework.data.mapping.MappingException: Couldn't find PersistentEntity for type java.lang.Object!
 at org.springframework.data.mapping.context.MappingContext.getRequiredPersistentEntity(MappingContext.java:119)
 at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:248)
 at org.springframework.data.mapping.context.PersistentPropertyPathFactory.from(PersistentPropertyPathFactory.java:176)
 at org.springframework.data.mapping.context.AbstractMappingContext.doFindPersistentPropertyPaths(AbstractMappingContext.java:322)
 at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.findPersistentPropertyPaths(JpaMetamodelMappingContext.java:100)
 at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory$MappingAuditingMetadata.<init>(MappingAuditableBeanWrapperFactory.java:115)
 at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.lambda$null$0(MappingAuditableBeanWrapperFactory.java:83)
 at java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:324)
 at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.lambda$null$1(MappingAuditableBeanWrapperFactory.java:82)
 at org.springframework.data.mapping.context.PersistentEntities.lambda$mapOnContext$4(PersistentEntities.java:115)
 at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
 at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
 at java.util.Spliterators$IteratorSpliterator.tryAdvance(Spliterators.java:1812)
 at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126)
 at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498)
 at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485)
 at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
 at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152)
 at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
 at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464)
 at org.springframework.data.mapping.context.PersistentEntities.mapOnContext(PersistentEntities.java:116)
 at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.lambda$getBeanWrapperFor$3(MappingAuditableBeanWrapperFactory.java:80)
 at java.util.Optional.flatMap(Optional.java:241)
 at org.springframework.data.auditing.MappingAuditableBeanWrapperFactory.getBeanWrapperFor(MappingAuditableBeanWrapperFactory.java:74)
 at org.springframework.data.auditing.AuditingHandler.touch(AuditingHandler.java:161)
 at org.springframework.data.auditing.AuditingHandler.markCreated(AuditingHandler.java:131)
 at org.springframework.data.jpa.domain.support.AuditingEntityListener.touchForCreate(AuditingEntityListener.java:92)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.hibernate.jpa.event.internal.ListenerCallback.performCallback(ListenerCallback.java:35)
 at org.hibernate.jpa.event.internal.CallbackRegistryImpl.callback(CallbackRegistryImpl.java:97)
 at org.hibernate.jpa.event.internal.CallbackRegistryImpl.preCreate(CallbackRegistryImpl.java:57)
 at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:116)
 at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:192)
 at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:135)
 at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:62)
 at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:800)
 at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:785)
 at java.lang.reflect.Method.invoke(Method.java:498)
 at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:308)

This used to work when using spring-boot 2.0.7.RELEASE, but I am trying to upgrade to spring-boot 2.1.1.RELEASE (which uses spring-data-jpa:2.1.3.RELEASE).

From what I can tell, there is a "new" PersistentPropertyPathFactory that now uses the "actualType" to determine what type the Entity is that needs to be persisted. However, the "actualType" for my Entity ends up just be java.lang.Object because it isCollectionLike (i.e. my type is a Collection so it satisfies the Collection.class.isAssignableFrom(rawType) check).

Here is a simplified example of the Entity/Collection class:

@Entity
public class ContainerCollection<C extends Container> extends Container implements Collection<C> {

    @JoinTable(
        name = "mod_container_collections",
        joinColumns = @JoinColumn(name = "container_collection_id"),
        inverseJoinColumns = @JoinColumn(name = "container_id"))
    protected Set<C> containers = new HashSet<>();

    @Override
    public int size() {
        return containers.size();
    }

    @Override
    public boolean isEmpty() {
        return containers.isEmpty();
    }

    // other Collection methods implemented to delegate to containers
    // with some relationship management in add(Object) and remove(Object)

}

And here is a really simple test that demonstrates the exception:

public class PersistenceTest {

    @PersistenceContext
    private EntityManager em;

    public void testPersist() {
        ContainerCollection<> collection = new ContainerCollection<>();
        em.persist(collection);  // this line throws MappingException
    }

}

Affects: 2.1.3 (Lovelace SR3)

Reference URL: https://stackoverflow.com/questions/53952858/how-do-i-persist-an-entity-which-implements-collection

@spring-projects-issues spring-projects-issues added type: bug in: mapping labels Dec 30, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: mapping type: bug
Projects
None yet
Development

No branches or pull requests

2 participants