Architecture
JPA
Mapping
Mapping - ID
There are three strategies to use a compound primary key:
Mark it as @Embeddable and add to your entity class a normal property for it, marked with @Id.
Add to your entity class a normal property for it, marked with @EmbeddedId.
Add properties to your entity class for all of its fields, mark them with @Id,and mark your entity class with @IdClass, supplying the class of your primary key class.
The use of @Id with a class marked as @Embeddable is the most natural approach. The @Embeddable tag can be used for non-primary key embeddable values anyway. It allows you to treat the compound primary key as a single property, and it permits the reuse of the @Embeddable class in other tables.
The next most natural approach is the use of the @EmbeddedId tag. Here, the primary key class cannot be used in other tables since it is not an @Embeddable entity, but it does allow us to treat the key as a single attribute of some class.
Finally, the use of the @IdClass and @Id annotations allows us to map the compound primary key class using properties of the entity itself corresponding to the names of the properties in the primary key class. The names must correspond (there is no mechanism for overriding this), and the primary key class must honor the same obligations as with the other two techniques. The only advantage to this approach is its ability to “hide” the use of the primary key class from the interface of the enclosing entity. The @IdClass annotation takes a value parameter of Class type, which must be the class to be used as the compound primary key. The fields that correspond to the properties of the primary key class to be used must all be annotated with @Id.
Mapping - Date and Time
Mapping - Constraints
-
Unique
-
@Column(name = "book_id", unique = true)
:unique = true
will create a Unique Constraint on the single column with an auto-generated constraint name. -
For finer-grained control, like specifing the name of the constraint, use
@UniqueConstraint
annotation on the class. eg:@Table(name = "question", uniqueConstraints = { @UniqueConstraint(name = "UQ_QUESTION_CHAPTER_QUESTION_NUMBER", columnNames = {"chapter_id", "question_number"}) })
-
-
Foreign
-
Specifying a Foreign key constraint:
@JoinColumn(name = "chapter_id", foreignKey = @ForeignKey(name = "FK_QUESTION_CHAPTER"))
-
Mapping - Column insertable
insertable = false
andupdatable = false
are used to prevent the column from being included in the insert or update statement.- This is useful when the column is a derived value or when it is managed by the database (a column default vaule such as a timestamp or a generated value).
Design Patterns
Prefer composition to inheritance
- Relational database only supports the concept of composition.
composition mapping strategy
- @ManyToOne
- @ManyToMany
- Model a many-to-many association as a
java.util.Set
(opens in a new tab)
- Model a many-to-many association as a
- @OneToOne
inheritance mapping strategy
- A mapped superclass strategy, which maps all subclasses as entities to their own, independent database table without supporting polymorphic queries.
- A table-per-class strategy, which models all classes, including the superclass, as entities and maps them to independent database tables. This strategy supports polymorphic queries.
- A joined strategy, which maps the specific attributes of each entity to its own database table but does not include the attributes of the superclass. So, whenever you want to fetch one of the subentities, you need to join at least two tables: the one mapped by the superclass and the one mapped by the subclass.
- A single-table strategy, which maps all entities to the same database table. This table has columns for the attributes of all entities in the inheritance hierarchy.
Open Session in View anti-pattern
Troubleshooting
N+1 select
N
is the number of entities in parent table
.
N+1
problem occurs when you use FetchType.LAZY
for your entity associations. If you perform a query to select n-entities
and if you try to call any access method of your entity's lazy association
, Hibernate will perform n-additional
queries to load lazily fetched objects.
Solutions
- Use a
JOIN FETCH
clause in aJPQL/HQL
query - Use
@BatchSize
on the lazy association - The definition of a query-independent
@NamedEntityGraph
(JPA 2.1
).EntityGraphs
provides a way to formulate better performing queries by defining which entities need to be retrieved from the database usingSQL JOINS
.