27 Temmuz 2020 Pazartesi

JPA @PersistenceContex Anotasyonu

Giriş
Şu satırı dahil ederiz.
import javax.persistence.PersistenceContext;
Java EE dünyasında container tarafından yönetilen bir EntityManager nesnesidir.

Spring ile kullanıyorsak bir tane proxy inject edilir. Açıklaması şöyle. Her transaction için farklı bir EntityManager daha doğrusu Hibernate Session nesnesi kullanılır.
Proxied entity manager for @PersistenceContext
Thanks to this transaction-aware proxies, EntityManager injected as @PersistenceContext can be used as a thread-safe object. It means that each requests will be handled by its own EntityManager. Why EntityManager is used through a proxy ? By definition (JSR-317 Final Release, section "7.3 Obtaining an Entity Manager Factory"), EntityManager is not thread safe. But according to the Spring's documentation, EntityManager injected through @PersistenceContext is "thread-safe proxy for the actual transactional EntityManager".
Farklı olmasının açıklaması şöyle
You shouldn't use @Autowired. @PersistenceContext takes care to create a unique EntityManager for every thread. In a production application you can have multiple clients calling your application in the same time. For each call, the application creates a thread. Each thread should use its own EntityManager. Imagine what would happen if they share the same EntityManager: different users would access the same entities.
Bu proxy kodla transaction yaratılmasına izin vermez. Eğer denersek şöyle bir exception alırız
java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead
Bu PersistenceContext.EXTENDED halini kullanırsak da kodla transaction yaratılmasına izin vermez. Eğer denersek şöyle bir exception alırız
java.lang.IllegalStateException: Cannot obtain local EntityTransaction from a transaction-synchronized EntityManager
Örnek
Spring ile şöyle yaparız.
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;


@Transactional
@Repository
public class PasswordJpaDaoImpl implements PasswordJpaDaoCustom {

  @PersistenceContext
  private EntityManager em;
  ...
}
Örnek
Spring ile şöyle yaparız.
public interface CustomerRepositoryCustom {

  List<Customer> getByCompany(Long id, int page, int size);
}

@Transactional(readOnly = true)
public class CustomerRepositoryImpl implements CustomerRepositoryCustom {

  @PersistenceContext
  private EntityManager entityManager;

  public List<Customer> getByCompany(Long id, int page, int size) {
    ... 
  }

}
unitName Alanı
persistence.xml dosyasındaki isim ile aynı olmalıdır.
Örnek
Elimizde şöyle bir XML olsun.
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
  version="2.0">
  <persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <properties>
      <property name="javax.persistence.jdbc.driver"
        value="com.mysql.jdbc.Driver"/>
      <property name="javax.persistence.jdbc.user" value="root"/>
      <property name="javax.persistence.jdbc.password" value="mypassword"/>
      <property name="javax.persistence.jdbc.url"
         value="jdbc:mysql://localhost/ptbrowserdb"/>
      <property name="hibernate.dialect"
        value="org.hibernate.dialect.MySQLDialect"/>
  </properties>
  </persistence-unit>
</persistence>
Şöyle yaparız.
@PersistenceContext(unitName = "manager1")
private EntityManager entityManager;
type  Alanı
Açıklaması şöyle. Her transaction için aynı EntityManager daha doğrusu Hibernate Session nesnesi kullanılır.
Notice that you can inject an no thread-safe persistence context by using type="PersistenceContextType.EXTENDED" attribute in @PersistenceContext annotation.

Hiç yorum yok:

Yorum Gönder