hibernate-reactive icon indicating copy to clipboard operation
hibernate-reactive copied to clipboard

java.lang.ClassCastException: class java.lang.Long cannot be cast to class org.hibernate.action.internal.DelayedPostInsertIdentifier

Open BalusC opened this issue 3 years ago • 1 comments

Given the following minimal models in Hibernate Reactive version associated with Quarkus platform version 2.13.3.Final:

@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;

    @NotNull
    private String email;

    @ManyToOne(fetch = LAZY)
    private Organization organization;

    // getters+setters
}
@Entity
public class Organization {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    private Long id;

    @NotNull
    @ManyToOne(fetch = LAZY, optional = false)
    private Person createdBy;

    @NotNull
    private String name;

    @OneToMany(fetch = LAZY, mappedBy = "organization")
    private Set<Person> members = new HashSet<>();

    // getters+setters
}

And already having a Person with id=1 in database associated with Organization with id=1.

And having the following minimal "create organization" action:

var organization = new Organization();
organization.setName("ACME Corporation");
return sessionFactory.withTransaction(session -> session.find(Person.class, 1L).chain(person -> {
    organization.setCreatedBy(person);
    return session.persist(organization).replaceWith(organization);
}));

Then following excepiton will be thrown:

Caused by: java.lang.ClassCastException: class java.lang.Long cannot be cast to class org.hibernate.action.internal.DelayedPostInsertIdentifier (java.lang.Long is in module java.base of loader 'bootstrap'; org.hibernate.action.internal.DelayedPostInsertIdentifier is in unnamed module of loader io.quarkus.bootstrap.classloading.QuarkusClassLoader @442675e1)
	at org.hibernate.action.internal.DelayedPostInsertIdentifier.compareTo(DelayedPostInsertIdentifier.java:25)
	at org.hibernate.internal.util.compare.ComparableComparator.compare(ComparableComparator.java:23)
	at org.hibernate.internal.util.compare.ComparableComparator.compare(ComparableComparator.java:18)
	at org.hibernate.type.AbstractStandardBasicType.compare(AbstractStandardBasicType.java:211)
	at org.hibernate.action.internal.CollectionAction.compareTo(CollectionAction.java:160)
	at org.hibernate.engine.spi.ExecutableList.add(ExecutableList.java:227)
	at org.hibernate.reactive.engine.ReactiveActionQueue.addAction(ReactiveActionQueue.java:403)
	at org.hibernate.reactive.engine.ReactiveActionQueue.addAction(ReactiveActionQueue.java:455)
	at org.hibernate.reactive.event.impl.AbstractReactiveFlushingEventListener.lambda$flushCollections$7(AbstractReactiveFlushingEventListener.java:228)
	at org.hibernate.engine.internal.StatefulPersistenceContext.forEachCollectionEntry(StatefulPersistenceContext.java:1136)
	at org.hibernate.reactive.event.impl.AbstractReactiveFlushingEventListener.flushCollections(AbstractReactiveFlushingEventListener.java:224)
	at org.hibernate.reactive.event.impl.AbstractReactiveFlushingEventListener.lambda$flushEverythingToExecutions$2(AbstractReactiveFlushingEventListener.java:105)
	at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757)
	at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735)
	at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2182)
	at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:144)
	at org.hibernate.reactive.event.impl.AbstractReactiveFlushingEventListener.flushEverythingToExecutions(AbstractReactiveFlushingEventListener.java:94)
	at org.hibernate.reactive.event.impl.DefaultReactiveFlushEventListener.reactiveOnFlush(DefaultReactiveFlushEventListener.java:41)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.lambda$fireEventOnEachListener$0(EventListenerGroupImpl.java:133)
	at java.base/java.util.concurrent.CompletableFuture.uniComposeStage(CompletableFuture.java:1187)
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:2309)
	at java.base/java.util.concurrent.CompletableFuture.thenCompose(CompletableFuture.java:144)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:133)
	at org.hibernate.reactive.session.impl.ReactiveSessionImpl.doFlush(ReactiveSessionImpl.java:929)
	... 95 more

The exception goes away when:

  1. EITHER members property is removed from Organization
  2. OR when Person with id=1 does NOT have any Organization associated
  3. OR when organization property of Person is set to fetch=EAGER instead of fetch=LAZY
  4. OR when organization.setMembers(null) is explicitly invoked in that person -> {} lambda (my work around for now)

So I guess something's gone wrong with proactively detecting of the cyclic lazy relationship.

BalusC avatar Nov 22 '22 12:11 BalusC

Thanks @BalusC.

I was able to recreate the error adapting one of the quickstarts: https://github.com/DavideD/quarkus-quickstarts/commit/ce16e7e80a9251eb2b2f02faaaf5315fc93d1b21

I don't have a solution. I think it might be related to an issue about many-to-one lazy associations that I've already fixed but we haven't released yet.

I will have a better look soon.

DavideD avatar Nov 22 '22 15:11 DavideD