Simple Mapping
@Entity
The @Entity
annotation is used to decorate immutable interfaces to represent ORM entities.
- Java
- Kotlin
@Entity
public interface Book {
...Omit other code...
}
@Entity
interface Book {
...Omit other code...
}
Why are entity types interfaces instead of classes?
Jimmer entities have
and , which are not simple POJOs with intricate internal workings that cannot be accomplished manually or with lombok assistance.So Jimmer lets developers write interfaces that are implemented at compile time by preprocessors (AnnotationProcessor for Java, KSP for Kotlin).
@Table
The @Table
annotation specifies the table name for the entity. If @Table
annotation is not used, e.g.
- Java
- Kotlin
@Entity
public interface BookStore {
...Omit other code...
}
@Entity
interface BookStore {
...Omit other code...
}
Jimmer will deduce the table name corresponding to the BookStore
interface based on the naming strategy.
If the default naming strategy is not overridden by the user, the table name for interface BookStore
is BOOK_STORE
. So the previous code is equivalent to:
- Java
- Kotlin
@Entity
@Table(name = "BOOK_STORE")
public interface BookStore {
...Omit other code...
}
@Entity
@Table(name = "BOOK_STORE")
interface BookStore {
...Omit other code...
}
@Column
The @Column
annotation specifies the database column for ordinary non-associative properties. If @Column
annotation is not used, e.g.
- Java
- Kotlin
@Entity
public interface BookStore {
String firstName();
...Omit other code...
}
@Entity
interface Author {
val firstName: String
...Omit other code...
}
Jimmer will deduce the column name corresponding to the firstName
property based on the naming strategy.
If the default naming strategy is not overridden by the user, the column name for property firstName
is FIRST_NAME
. So the previous code is equivalent to:
- Java
- Kotlin
@Entity
public interface BookStore {
@Column(name = "FIRST_NAME")
String firstName();
...Omit other code...
}
@Entity
interface Author {
@Column(name = "FIRST_NAME")
val firstName: String
...Omit other code...
}
@Column
is only used to explicitly specify column names for non-associative properties. For foreign key column names of many-to-one or one-to-one association properties, they must be specified through @JoinColumn
. See Association Mapping for more.
@Id
Declare a property as the id property, as follows
- Java
- Kotlin
@Entity
public interface Book {
@Id
long id();
}
@Entity
interface Book {
@Id
val id: Long
}
The id field must be non-null (for Java, long
is used here instead of Long
)
Unlike JPA, which encourages declaring the id as a nullable type, Jimmer does not use this method to express not specifying the id during data insertion. The dynamism of Jimmer objects themselves can easily express this problem.
See Nullity for details.
@GeneratedValue
In the previous example, the primary key property decorated with @Id
is a business field that must be specified when inserting data.
However, more often, we expect that the primary key property itself has no business meaning, so that it can be unspecified when inserting data and automatically generated instead. The automatic id generation strategies are:
- Database autoincrement
- Database sequence
- UUID
- Snowflake ID
@GeneratedValue
works with @Id
to specify auto growth strategy for Id.
Database autoincrement
- Java
- Kotlin
@Entity
public interface Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
long id();
}
@Entity
interface Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
val id: Long
}
Database sequence
- Java
- Kotlin
@Entity
public interface Book {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
long id();
}
@Entity
interface Book {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
val id: Long
}
Here, the sequence name in the database is not specified through the sequenceName
of @GeneratorValue
. Jimmer will deduce the sequence name based on the naming strategy.
If the default naming strategy is not overridden by the user, the sequence name here is BOOK_ID_SEQ
. So the previous code is equivalent to:
- Java
- Kotlin
@Entity
public interface Book {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
sequenceName = "BOOK_ID_SEQ"
)
long id();
}
@Entity
interface Book {
@Id
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
sequenceName = "BOOK_ID_SEQ"
)
val id: Long
}
UUID
Setting the generatorType property of @GeneratedValue
to org.babyfish.jimmer.sql.meta.UUIDIdGenerator
can be used to randomly generate UUIDs
- Java
- Kotlin
@Entity
public interface Book {
@Id
@GeneratedValue(generatorType = UUIDIdGenerator.class)
UUID id();
}
@Entity
interface Book {
@Id
@GeneratedValue(generatorType = UUIDIdGenerator::class)
val id: UUID
}
Custom IdGenerator
When the above Id growth strategies cannot meet the requirements, a custom Id generation strategy can be defined.
Jimmer provides an UserIdGenerator<T>
interface
package org.babyfish.jimmer.sql.meta;
public interface UserIdGenerator<T> extends IdGenerator {
T generate(Class<?> entityType);
}
Users can implement this interface to implement any Id generation algorithm, including snowflake ID.
package com.mycompany.myproject.common;
public class MyIdGenerator implements UserIdGenerator<Long> {
@Override
public Long generate(Class<?> entityType) {
return ...Omit custom id generation logic...
}
}
- Java
- Kotlin
@Entity
public interface Book {
@Id
@GeneratedValue(generateType = MyIdGenerator.class)
Long id();
}
@Entity
interface Book {
@Id
@GeneratedValue(generateType = MyIdGenerator::class)
val id: Long
}
The user-implemented Id generation class MyIdGenerator
itself does not have generic parameters, but generic parameters must be specified for the super interface UserIdGenerator
.
The type of the decorated Id property must be consistent with this generic parameter, otherwise an exception will be thrown.