Skip to content
Bluetape4k docs1.11

Entity model and lifecycle

Latest stable Based on Bluetape4k release 1.11.0

Hibernate entities move through transient, managed, and detached states. persist, merge, lazy loading, and dirty checking behave differently in each state.

IntJpaEntity and LongJpaEntity use IDENTITY, so their IDs normally appear after insert. UuidJpaEntity assigns UUID v7 during construction. Because this module defines isPersisted as id != null, a UUID entity reports persisted before its first insert. Do not use isPersisted as a database-existence check.

@Entity
class Account(var email: String = ""): LongJpaEntity() {
override fun equalProperties(other: Any): Boolean =
other is Account && email == other.email
}

identifier throws IllegalStateException while the ID is null.

AbstractJpaEntity.equals compares IDs when both entities are persisted, uses equalProperties when both are transient, and rejects a mixed persisted/transient pair. It unproxies Hibernate proxies before comparison.

The 1.11.0 hash contract has a known limitation: two transient instances can be equal by business signature but have different identity hash codes. The later class-based hash fix is not 1.11.0 behavior.

  • Do not use transient entities as deduplication keys in HashSet or HashMap.
  • Do not keep an entity in a hash collection while its persistence state changes.
  • Use a stable business-key value object outside the persistence boundary.

IntJpaTreeEntity and LongJpaTreeEntity map parent and children. addChildren and removeChildren update both sides in memory. CascadeType.ALL means the deletion policy must match the domain.

getReference may return an uninitialized proxy. Read required associations or map the entity to a DTO inside the transaction. isLoaded can inspect initialization but does not replace an explicit fetch plan.

Terminal window
./gradlew :bluetape4k-hibernate:test --tests '*JpaEntityModelTest'
./gradlew :bluetape4k-hibernate:test --tests '*TreeNodeTest'