web-dev-qa-db-fra.com

différentes manières d'obtenir EntityManager

L'idiome habituel que je vois pour créer EntityManager ressemble à ceci:

public class BaseDao {

private static final String PERSISTENCE_UNIT_NAME = "Employee";
EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

public EntityManager getEntityManager() {
      return factory.createEntityManager();
    } 
}

alors il est utilisé comme ceci:

Employee emp = new Employee();
emp.setName("Joe M");
getEntityManager().persist(emp);

La question est pourquoi ne pas le faire de cette façon:

public class BaseDao{
    private static final String PERSISTENCE_UNIT_NAME = "Employee";
    EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    private EntityManager entityManager = null;


public void setEntityManger() {
        EntityManagerFactory factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
    this.entityManager = factory.createEntityManager();

    }

    public EntityManager getEntityManager() {
        return this.entityManager;
    }
}

En d'autres termes, est-il nécessaire de toujours obtenir le gestionnaire d'entités via factory.createEntityManager ()? ou peut-il être créé comme une variable d'instance (ou même statique) et récupéré comme ça?

Pour clarifier, je parle d'un environnement qui n'utilise pas de conteneurs EJB ou Spring.

Merci.

28
jayjay

Il existe deux manières de créer des instances EntityManager. L'une d'elles est destinée aux applications SDK, et j'utilise beaucoup cette méthode lors des tests unitaires. Voici ce que vous avez dans votre exemple:

EntityManagerFactory factory = 
  Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

Dans les applications d'entreprise, vous laissez le conteneur les créer pour vous et les injecter si besoin.

EntityManager est juste un wrapper autour d'une connexion JDBC. Il est très léger et peut être créé et détruit sans pénalité de performance. 

N'oubliez pas que la variable EntityManager n'est pas thread-safe. Par conséquent, si vous avez une instance, vous devrez peut-être synchroniser l'accès à celle-ci. Voir bases de la transaction pour plus de détails.


Voici comment je le ferais (à peu près):

public class BaseDao{
  private static final String PERSISTENCE_UNIT_NAME = "Employee";
  private static EntityManagerFactory factory = 
    Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

  public void create(MyEntiy person){
    EntityManager em = factory.createEntityManager();
    em.getTransaction().begin();
    // do what ever you need 
    em.getTransaction().commit();
    em.close();
  }

  // add more methods to the dao.
}

Une fois que vous obtenez ce prototype et prêt, vous pouvez utiliser un DAO générique.

14
Mansour

Aujourd'hui, vous devriez probablement regarder parfois Spring-data et @PersistanceUnit pour gérer votre EntityManager.

Un EntityManager est plus qu'un simple wrapper, un wrapper pour une connexion JDBC. Il définit l'étendue d'un contexte de persistance, qui définit l'unité de travail à exécuter lorsqu'une transaction est validée (ou lorsque vous videz des requêtes dans la base de données). Dans un contexte de persistance, vous avez également la garantie qu'une entité donnée de la base de données générera le même objet Java, que vous le chargiez directement ou que vous y accédiez via une relation OneToMany d'une autre entité.

En ce qui concerne la question initiale relative à l’obtention d’une EntityManagerFactory dans un paramètre autre que le ressort. Vous appelez simplement 

Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);

Cette méthode est une méthode de fabrique statique. Selon votre implémentation JPA, vous obtenez soit la même instance pour le même PU, soit un wrapper peu profond qui encapsule la session de persistance sous-jacente (il en existe une par PU).

1
Klaus Groenbaek