🦴 Spring JPA Persistence Context

GunhoΒ·2024λ…„ 11μ›” 17일
1

Object Oriented Programming (OOP) & Java

λͺ©λ‘ 보기
20/29

🦴 Spring JPA Persistence Context

🦴 Persistence Context is a storage where a set of entities with unique identities are persisted.

Persistence Context is a logical concept without its physical presence and is accessible via EntityManager that handles the lifecycle of all entities and database resources such as db connections.

Persistence Context provides underneath features:

  • πŸ”Ž First-Level Cache
  • ✍️ Transactional Write-Behind
  • βœ”οΈ Dirty Checking
  • 🚽 Flush

where these will be discussed in the following sections.

πŸ’‘ NOTES

πŸ§‘β€βš•οΈ An Entity Manager is responsible for performing persistence logic by interacting with the persistence context and changing the state of entities. The Entity Manager can change the state of an entity using methods such as persist, merge, remove, and close. Additionally, the Entity Manager can retrieve entities from the first-level cache of the persistence context and synchronise with the database by flushing queries stored in the transactional write-behind. It is also possible to fetch data directly from the database using JPQL or Native Query.


🐣 Entity Life Cycle

πŸ₯ Entity refers to a piece of data that is stored in the database.

In Spring JPA, entity can be represented with the @Entity annotation, and annotated classes are then identified by Spring JPA as a frame that should contain data from the database in which Spring JPA executes automatic mapping.

Below could be a good example of a class with @Entity annotation:

Item Entity

@Entity
@Getter @Setter
public Item {
	@Id
    @GenereatedValue
    private Long id;
    
    private String name;
}

Entity lifecycle with its graphical representation can be summarised as below:

  • 🐣 new/transient

    • a state where an entity is a pure Java object.
    • no relation to a persistence context.
  • πŸ§‘β€πŸŒΎ managed

    • a state managed by a persistence context.
  • πŸ“ detached

    • a state once managed by a persistence context but currently detached.
  • πŸ— removed

    • a state removed from a persistence context and a database.
μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° - 기본편 Available at here

In JPA, the above state can be achieved via the underneath code:

JPA (Entity Lifecycle)

EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
EntityManager em = emf.getEntityManager();

// new/transient
Item item = new Item();
item.setId(1L);
item.setName("item1");

// managed
em.persist(item);
Item findItem = em.find(Item.class, 1L);

// detached
em.detach(findItem);
em.clear();
em.close()

// remove
em.remove(findItem);

πŸ”Ž First-Level Cache

πŸ”Ž First-Level Cache is a cache within a persistence context where an entity is stored in a HashMap as a key-value pair (id = @id, value = entity instance).

Via first-level cache, equality across identical entities becomes secured as a specified @id becomes an identifier to retrieve a cached value.

Any managed entities becomes retrievable from a first-level cache once a relevant persist() and find() method calls are invoked.

Specifically, persist() will save an entity in a first-level cache while find() will look up a database and then store the retrieved data into a first-level cache if there is no cache data so that for the sequential find() calls, the cached data becomes retrieved without necessarily connecting to the database.

The overall process can be graphically illustrated as below:

μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° - 기본편 Available at here

A persistence context only exists within a single transaction, implying that a first-level cache only exists within a single transaction as well. Hence, performance-wise, first-level cache appears not to be considerable.

✍️ Transactional Write-Behind

✍️ Transactional Write-Behind is a feature where any updates invoking SQL queries to a database are deferred until the transaction commits.

The introduction of transactional write-behind deeply underlies in TCP connection between an application and a database in which connection is costly, and hence, sending all the SQL queries at once becomes a cost-effective practice.

Underneath presents good visual notations:

μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° - 기본편 Available at here

βœ”οΈ Dirty Checking

βœ”οΈ Dirty Checking is a mechanism that a persistence context tracks changes over the managed entities.

Dirty Checking was introduced following inconvenience and performance issues related to changes over entities where an update SQL query had to be created for every entity update:

Updates

Item item = em.find(Item.class 1L);

item.setName("Hello");  -> UPDATE ... SET NAME = ? 
item.setQuantity(1);    -> UPDATE ... SET QUANTITY = ? 

Dirty Checking prevents the above inefficiency by introducing the snapshot of an entity where the snapshot refers to the initial version of the entity from a database. Persistence context then compares the snapshot to the entity with the final updates and constructs a single SQL UPDATE statement.

μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° - 기본편 Available at here

🚽 Flush

🚽 Flush refers to a JPA mechanism where all the updates within a persistence context becomes reflected to a database.

Flush does not necessarily empty a persistence context, but simply synchronises all the latest changes over managed entities that is persisted as transactional write-behind to a database.

Flush can be invoked by as below:

  • em.flush() - manual
  • transaction commit - auto
  • JPQL query execution - auto

and flushing options can be altered in accordance to developers' demand via entity manager's setFlushMode setter().

JPA (flush)

em.setFlushMode(FlushModeType.AUTO) // default
em.setFlushMode(FlushModeType.COMMIT) // manual flush

πŸ“š References

μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ° - 기본편 (κΉ€μ˜ν•œ)
μžλ°” ORM ν‘œμ€€ JPA ν”„λ‘œκ·Έλž˜λ°

profile
Hello

0개의 λŒ“κΈ€