I have the following entities:

Note:

@Entity
@DynamicUpdate
@Table(name = "note")
class Note(
    notebookId: UUID,
    @Column(length = 128, nullable = false) var title: String,
    @Column(length = 65536) var content: String?
) {

    @EmbeddedId
    val id = NoteId(notebookId, UUID.randomUUID())

    override fun equals(other: Any?) = when {
        this === other -> true
        other == null || Hibernate.getClass(this) != Hibernate.getClass(other) -> false
        else -> other is Note && id == other.id
    }

    override fun hashCode() = id.hashCode()

    override fun toString() =
        "Note(notebookId=${id.notebookId}, title='$title', content='$content', nodeId=${id.noteId})"
}

@Embeddable
data class NoteId(
    @Column(columnDefinition = "uuid") val notebookId: UUID,
    @Column(columnDefinition = "uuid") val noteId: UUID
) : Serializable

Notebook:

@Entity
@Table(name = "notebook")
@EntityListeners(AuditingEntityListener::class)
class Notebook(
    @Column(length = 128, nullable = false) var title: String,
    @Column(length = 1024) var description: String?
) {

    @Id
    @Column(columnDefinition = "uuid")
    var id: UUID = UUID.randomUUID()

    @Column(updatable = false, nullable = false)
    val createdAt: OffsetDateTime = OffsetDateTime.now()

    @LastModifiedDate
    @Column(nullable = false)
    lateinit var lastModified: OffsetDateTime

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "id.notebookId", cascade = [CascadeType.ALL], orphanRemoval = true)
    var notes: MutableSet<Note> = mutableSetOf()
        set(value) {
            field.clear()
            field.addAll(value)
        }

    override fun equals(other: Any?) = when {
        this === other -> true
        other == null || Hibernate.getClass(this) != Hibernate.getClass(other) -> false
        else -> other is Notebook && id == other.id
    }

    override fun hashCode() = id.hashCode()

    override fun toString() = "Notebook(id=$id, title='$title', description=$description, createdAt=$createdAt, " +
        "lastModified=$lastModified, notes=${notes.size})"
}

This yields in the following error on startup:

Caused by: org.hibernate.MappingException: Could not find appropriate constructor for org.hibernate.persister.collection.OneToManyPersister
    at org.hibernate.persister.internal.PersisterFactoryImpl.resolveCollectionPersisterConstructor(PersisterFactoryImpl.java:218) ~[notes:6.1.3.Final]
    at org.hibernate.persister.internal.PersisterFactoryImpl.createCollectionPersister(PersisterFactoryImpl.java:163) ~[notes:6.1.3.Final]
    at org.hibernate.persister.internal.PersisterFactoryImpl.createCollectionPersister(PersisterFactoryImpl.java:155) ~[notes:6.1.3.Final]
    at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.processBootCollections(MappingMetamodelImpl.java:341) ~[na:na]
    at org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl.finishInitialization(MappingMetamodelImpl.java:218) ~[na:na]
    at org.hibernate.metamodel.internal.RuntimeMetamodelsImpl.finishInitialization(RuntimeMetamodelsImpl.java:60) ~[na:na]
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:308) ~[notes:6.1.3.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:415) ~[notes:6.1.3.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1425) ~[notes:6.1.3.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:66) ~[na:na]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:376) ~[notes:6.0.0-M6]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[notes:6.0.0-M6]
    ... 20 common frames omitted

Adding OneToManyPersister constructor as type hint solved the problem:

class AotConfig : RuntimeHintsRegistrar {
    override fun registerHints(hints: RuntimeHints, classLoader: ClassLoader?) {
        hints.reflection().registerType(OneToManyPersister::class.java, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)
    }
}

Comment From: sdeleuze

This kind of issue should be reported on https://github.com/oracle/graalvm-reachability-metadata side, and has already be fixed via https://github.com/oracle/graalvm-reachability-metadata/pull/68 that is available in GraalVM reachability repository 0.2.2+.