Package st.orm

Annotation Interface PK


Marks a field as the primary key of an entity. This annotation can also specify the database column name for the primary key using either value() or name(). These attributes are aliases: if both are provided, they must have the same value.

Usage examples:

  • @PK("id")
  • @PK(name="id")
  • @PK @DbColumn("id")
Each sets the primary key column name to "id".

If no value is specified (i.e., both value() and name() are ""), the automatic column name resolution strategy will be applied.

Composite Primary Keys

For composite primary keys, define a separate record containing the key components and use it as the primary key field.

Java:


 record UserRolePk(int userId, int roleId) {}

 record UserRole(@PK UserRolePk pk,
                 @FK @Persist(insertable = false, updatable = false) User user,
                 @FK @Persist(insertable = false, updatable = false) Role role
 ) implements Entity<UserRolePk> {}
 

Kotlin:


 data class UserRolePk(val userId: Int, val roleId: Int)

 data class UserRole(@PK val pk: UserRolePk,
                     @FK @Persist(insertable = false, updatable = false) val user: User,
                     @FK @Persist(insertable = false, updatable = false) val role: Role
 ) : Entity<UserRolePk>
 

The @Persist annotation indicates that the FK columns overlap with the composite PK columns. The FK fields are used to load the related entities, but the column values come from the PK during insert/update operations.

Primary Key as Foreign Key

A primary key can also be a foreign key, which is useful for dependent one-to-one relationships, extension tables, or table-per-subtype inheritance. Use both @PK and @FK on the same field with generation = NONE.

Java:


 record UserProfile(@PK(generation = NONE) @FK User user,
                    String bio
 ) implements Entity<User> {}
 

Kotlin:


 data class UserProfile(@PK(generation = NONE) @FK val user: User,
                        val bio: String
 ) : Entity<User>
 

Column name resolution when both @PK and @FK are present:

  1. Explicit name in @PK (e.g., @PK("user_profile_id"))
  2. Explicit name in @DbColumn
  3. Foreign key naming convention (default)
See Also:
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    boolean
    Indicates whether a corresponding primary key constraint is expected to exist in the database.
    The primary key generation strategy.
    The database column name for the primary key.
    The sequence name for the primary key.
    The database column name for the primary key.
  • Element Details

    • value

      String value
      The database column name for the primary key. Acts as an alias for name().
      Default:
      ""
    • name

      String name
      The database column name for the primary key. Acts as an alias for value().
      Default:
      ""
    • generation

      GenerationStrategy generation
      The primary key generation strategy. Default value is GenerationStrategy.IDENTITY.
      Returns:
      the primary key generation strategy.
      Default:
      IDENTITY
    • sequence

      String sequence
      The sequence name for the primary key. The sequence must only be used with GenerationStrategy.SEQUENCE. Default value is "".
      Returns:
      the sequence name.
      Default:
      ""
    • constraint

      boolean constraint
      Indicates whether a corresponding primary key constraint is expected to exist in the database.

      When true (the default), schema validation will check that the database table has a primary key constraint matching the entity's primary key columns. Set to false when the database intentionally omits the primary key constraint, for example for legacy tables without constraints.

      Setting this to false only suppresses the constraint check during schema validation. The field is still fully functional as a primary key for Storm's identity resolution and query generation.

      Returns:
      true if the primary key constraint is expected in the database, false to skip the check.
      Since:
      1.10
      Default:
      true