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

Check MapsId with custom id generation

Open DavideD opened this issue 1 year ago • 0 comments

Related to this question on Stack Overflow.

Entity Example:

@Id
@GeneratedValue(generator = "SharedPrimaryKeyGenerator")
@GenericGenerator(
    name = "SharedPrimaryKeyGenerator",
    strategy = "foreign",
    parameters = [Parameter(name = "property", value = "bookLineItem")]
)
@Column(
    name = ENTITY_B_ID,
    unique = true,
    nullable = false
)
var entityBId: Int? = null

@OneToOne
@PrimaryKeyJoinColumn
@JsonBackReference
var entityA: EntityA? = null

Custom generator:

 class ReactiveSharedPrimaryKeyGenerator: ReactiveIdentifierGenerator<Int> {
    override fun generate(p0: ReactiveConnectionSupplier?, entity: Any?): CompletionStage<Int> {
        return CompletableFuture.supplyAsync {
            val primaryKey = getPrimaryKey(entity!!)
            primaryKey as Int ?: throw IllegalStateException("Primary Key value is null")
        }.toCompletableFuture()
    }

    /**
     * Returns the ID or the One2One parent by checking for the @PrimaryKeyJoinColumn field to retrieve the parent
     * and then searches for the field annotated with @Id to retrieve the ID of the parent
     */
    fun getPrimaryKey(entity: Any?): Int? {
        entity?.let {
            var currentClass: Class<*> = it::class.java
            while (currentClass != null && currentClass != Any::class.java) {
                currentClass.declaredFields.forEach { field ->
                    val annotation = field.getAnnotation(PrimaryKeyJoinColumn::class.java)
                    annotation?.let { an ->
                        field.trySetAccessible()
                        val primaryKeyOwner = field.get(it)
                        primaryKeyOwner?.let { pk ->
                            val primaryKeyField = pk::class.java.getDeclaredFields().find { pkF ->
                                pkF.getAnnotation(javax.persistence.Id::class.java) != null
                            }
                            if (primaryKeyField != null) {
                                primaryKeyField.trySetAccessible()
                                val pkId = primaryKeyField.get(pk)
                                return pkId as Int?
                            }
                        }

                    }
                }
                currentClass = currentClass.superclass
            }
        }
        return null
    }
}

If somebody wants to provide a test, we a similar use case in OneToOneMapsIdTest, except that it doesn't use a custom generator.

DavideD avatar May 21 '24 10:05 DavideD