3. Hold database connection too long
5. Tips, Tricks and have to know
This chapter is about Spring Data JPA with as implementation Hibernate.
spring.jpa.open-in-view=false
Let the business layer decide when it should start and stop an transaction (with @transactional or transactionTemplate).
If this is set to true the transaction will be held during the whole rendering phase.
Transaction will be held until something is returned from the request, so if you have an IO intensive request you will hold the transaction and the db connection during that time.
spring.jpa.auto-commit=false
Again let the business layer decide when a entity should be saved.
Saves on db resources.
hibernate.query.fail_on_pagination_over_collection_fetch=true
Let hibernate fail if sorting is happening in memory and not on database level. This can happen when using sorting together with entity graphs.
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=false
Anti-pattern!! Do not use. Is normally used when you want to fetch objects outside of the hibernate lifecycle. So you can avoid LazyInitializationException.
if you lazy fetch a Many relation you will fetch the relation one by one resulting in database performance issues. Solutions:
When overriding the default lazy fetch plan for ToMany relations (where a class has a list/set). You fetch everything with left outer join, as (legacy/default) databases do not have array concepts, you fetch a row per relation, resulting in a row per relation item. If have a parent with 4 childeren and these 4 childeren have each 3 childeren on their own you would get 4x3= 12 rows back. This example is small but even with small quantities you can have big results: 100 items x 1000 subitems = 10 000 rows returned. So even with small quantities you begin to overload your db and application.
Try to avoid the cartesian Product and use Lazy loading for fetching multiple relations! You can also get MutipleBagFetchException from eager loading Many relations, use a set or ordered list.
<T> findBy...
. So you can dynamically choose what you need to fetch by choosing which class you use to fetch.import jakarta.persistence.*;
// How the entity should be named,
// you can use this in
// Jakarta Persistence Query Language or Hibernate Query Language
@Entity("note")
// On which database table the entity should map
@Table("note_v2")
public class Note {
@Id
@GenerateValue(strategy = GenerationType.UUID)
private UUID uuid;
/**
* Optional, can be used on columns that are directly mapped.
* changes on annotation are only applicable to the variable not the database column.
* Has 2 attributes, optional (should allow null) and fetch (fetchType Eager or Lazy)
* Lazy loading can be used for serializable objects which can be big --> blob like formate for images
*/
@Basic(optional = false, fetch = FetchType.LAZY)
/**
* Column can be used in conjunction with other annotations (basic, ...)
* Is used for mapping on database columns
*
*/
@Column(name = "name_v2")
private String name;
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "date_created")
private ZonedDateTime dateCreated;
@UpdateTimestamp
/**
* Mapped on Date or Time objects, is used to specify how the time data is stored
* java.sql. --> Timestamp, Time Date
*/
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "date_updated")
private ZonedDateTime dateUpdated;
/**
* The @Lob annotation specifies that the database should store the property as Large Object.
* The columnDefinition in the @Column annotation defines the column type for the property.
*/
@Lob
@Column(name = "photo", columnDefinition="BLOB")
private byte[] photo;
}
HibernateType | Description |
---|---|
Bag | Can contain duplicates and no order |
List | Can contain duplicates but with order reserved. @OrderBy on list. |
Set | No duplicates and no order |
JavaListType | HibernateListType | Description | Performance |
---|---|---|---|
List | Bag | Allows duplicate elements in it - unordered. | Bad needs an extra column for ordering, after deleting reordering is required |
Ordered List | List | Allows duplicate elements in it - is ordered | Bad needs an extra column for ordering, after deleting reordering is required |
Set | Set | All elements should be unique. | Good does not need reordering after deleting of element |
sources:
https://stackoverflow.com/questions/17543027/what-to-choose-between-set-and-list-in-hibernate
Always define FetchType to Lazy!!
Relation | DefaultFetchType |
---|---|
@ManyToOne | Eager |
@OneToOne | Eager |
@OneToMany | Lazy |
@ManyToMany | Lazy |
@Table("parent")
@Entity("parent")
public class Parent {
@OneToMany
@JoinColumn(name = "fk_child")
private Set<Child> children = new HashSet<Child>();
// helper method
public void AddChild(Child child) {
this.children.add(child);
child.setParent(this);
}
}
public class Child {
@ManyToOne
private Parent parent;
}
cascadeTypes?, orphanRemoval?, inverseJoinColumns, fetchModes
optimistic locking vs pessimistic locking
have a look at tooling: flexypool, digma, QuickPerf
How JOOQ fits with JPA.
@embeddable, @ElementCollection, @collectiontable,@optimisticLocking
ANSI SQL isolation levels
best practices relations
How to map inheritance —> multiple solutions