Skip to content

Check MapsId with custom id generation #1912

Open
@DavideD

Description

@DavideD

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    testingImprovements to test suite

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions