Setting auto-generated Ids manually with Hibernate
In this tutorial, you will learn how to implement a custom IdentifierGenerator
to support auto-generated and manually assigned Ids using Hibernate.
In this tutorial, you will learn how to implement a custom IdentifierGenerator
to support auto-generated and manually assigned Ids using Hibernate.
package com.matchilling.lib.hibernate | |
import org.hibernate.engine.spi.SharedSessionContractImplementor | |
import org.hibernate.id.IdentifierGenerator | |
import java.io.Serializable | |
import java.util.* | |
import kotlin.reflect.full.declaredMemberProperties | |
import kotlin.reflect.jvm.javaType | |
class UuidGenerator : IdentifierGenerator { | |
override fun generate( | |
session: SharedSessionContractImplementor?, | |
instance: Any? | |
): Serializable { | |
val id = instance!!::class.declaredMemberProperties.find { | |
it.name == "id" && it.returnType.javaType.typeName == UUID::class.java.canonicalName | |
}?.getter?.call(instance) | |
return if (id != null) { | |
id as UUID | |
} else { | |
UUID.randomUUID() | |
} | |
} | |
companion object { | |
const val NAME = "uuid" | |
const val STRATEGY = "com.matchilling.lib.hibernate.UuidGenerator" | |
} | |
} |
package com.matchilling.lib.hibernate | |
import io.mockk.mockk | |
import org.hibernate.engine.spi.SharedSessionContractImplementor | |
import org.junit.Test | |
import org.junit.jupiter.api.Assertions.assertEquals | |
import java.util.* | |
internal class UuidGeneratorTest { | |
private val subject = UuidGenerator() | |
private val uuid = Regex("[0-9a-fA-F]{8}(?:-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}") | |
internal class EntityImpl(val id: UUID?) | |
@Test | |
fun `should assign a random UUID if id prop is null`() { | |
// given | |
val instance = EntityImpl(id = null) | |
// and | |
val session = mockk<SharedSessionContractImplementor>() | |
// when | |
val id = subject.generate(session, instance) | |
// then | |
assert(id.toString().matches(uuid)) | |
} | |
@Test | |
fun `should not generate a new UUID when id prop is not null`() { | |
// given | |
val expected = UUID.fromString("d1f1ece1-c84b-465f-9529-0c3820c0c2d7") | |
// and | |
val instance = EntityImpl(id = expected) | |
// and | |
val session = mockk<SharedSessionContractImplementor>() | |
// when | |
val actual = subject.generate(session, instance) | |
// then | |
assertEquals(expected, actual) | |
} | |
} |