2010-11-01 28 views
4

J'ai quelques questions concernant l'utilisation du gestionnaire d'entités dans un environnement JavaSE. J'utilise le modèle de référentiel pour effectuer mes opérations CRUD sur la base de données. Il y aura une classe de dépôt de base comme ceci:JPA 2 - Utilisation de l'EntityManager dans JavaSE - quelques questions

public class Repository<T> implements IRepository<T> { 

    private EntityManager em; 
    private String persistenceUnitName; 

    public Repository(String persistenceUnitName) { 
     this.persistenceUnitName = persistenceUnitName; 
    } 

    @Override 
    public T find(Class<T> type, Object id) { 
     return em.find(type, id); 
    } 

    private EntityManager getEntityManager() { 
     if (this.em == null) { 
      EntityManagerFactory emf = Persistence.createEntityManagerFactory(persistenceUnitName); 

      em = emf.createEntityManager(); 
     } 

     return em; 
    } 
    ... 
    ... 
} 

Je vais donc avoir des classes comme EmployeeRepository qui hériteront Repository. Ces classes de référentiel seront créées dans ma couche de service.

Est-ce un bon moyen d'initialiser le gestionnaire d'entités? Je commence à penser que ce n'est pas - il semble que vous ne devriez avoir qu'un seul gestionnaire d'entité par unité de persistance? Où, comme dans ce cas, vous auriez un gestionnaire d'entité pour chaque référentiel que vous créez ... Comment vous assureriez-vous de n'avoir qu'un seul gestionnaire d'entité par unité de persistance? De plus, j'ai remarqué que les méthodes d'usine du gestionnaire d'entité et du gestionnaire d'entité ont une méthode proche - quand faut-il les appeler? Sur un serveur, terminez l'événement?

Si vous connaissez de bonnes sources sur l'utilisation de JPA dans JavaSE, j'apprécierais l'info.

Merci!

Répondre

3

Presque. Vous n'avez besoin que d'une EntityManagerFactory par unité de persistance.

Comment voulez-vous vous assurer de n'avoir qu'une entité EntityManagerFactory par unité de persistance?

Généralement les développeurs à créer une classe d'aide avec un EntityManagerFactory singleton tels que

public class EntityManagerFactoryHelper { 

    private static EntityManagerFactory factory; 

    static { 
     try { 
      // Set up factory right here 
     } catch(ExceptionInInitializerError e) { 
      throw e; 
     } 
    } 

    public static EntityManagerFactory getFactory() { 
     return this.factory; 
    } 

} 

EntityManager, dans d'autre part, est utilisé pour interagir avec un ensemble d'instances d'entités gérées appelé contexte de persistance.

Si vous voulez savoir pourquoi j'utilise ErrorInInitializerError, son API est clair

signaux qu'une exception inattendue est survenue dans un initialiseur statique

...

Est-ce un bon moyen d'initialiser le gestionnaire d'entités?

Eh bien, la couche de service est utilisé pour délimiter la limite de transaction. Donc pour chaque cas d'utilisation, vous pouvez créer votre EntityManager et passer par référence pour chaque colaborateur nécessaire pour vous aider à exécuter votre cas d'utilisation.

public static br.com.helper.EntityManagerFactoryHelper.getFactory; 

public EmployeeService { 

    public void doSomething() { 
     EntityManager eManager = getFactory().createEntityManager(); 
     eManager.getTransaction().begin(); 

     EmployeeRepository repository = new EmployeeRepository(eManager); 

     eManager.getTransaction().commit(); 
    } 

} 

Imaginez maintenant que vous avez besoin du code standard indiqué ci-dessus pour chaque cas d'utilisation.

public void forEachUseCase() { 
     // Create an EntityManager 
     // Begin a Transaction 

     EmployeeRepository repository = new EmployeeRepository(eManager); 

     // And finally, commit 
    } 

Vous pouvez compter sur Spring pour vous aider à vous débarrasser de ce code passe-partout.

+0

Je suis un peu en retard à ce sujet, mais savez-vous que si vous utilisez la persistance gérée par conteneur, et que vous recherchez une unité de persistance par son nom JNDI donné dans : EntityManager manager = (EntityManager) context.lookup (jndiName);), est-ce que EM retourné réellement un nouveau EM à chaque fois? Est-ce une EMF derrière la scène qui envoie des EM, ou est-ce juste une EM globale liée à un seul thread? – djb

0

Brian,

Il est correct de partager EntityManagerFactory, mais il est normal de partager EntityManager. Voir le Java Persistence wikibook.

Une approche plus moderne serait de faire des singletons avec des énumérations. Donc, en supposant que vous ne vous attendez pas à aller changer autour de vos noms de l'unité de persistance (j'attendre à ce que ne se produise pas de toute façon) ...

Donc, idéalement ...

  1. Utilisez un singleton pour la EntityManagerFactory instance, par unité de persistance.
  2. Créez un nouveau gestionnaire d'entité à chaque appel pour en extraire un et ne les partagez pas.

L'utilisation d'un ENUM pour le mécanisme singleton prévoit ... (Effective Java Second edition)

  1. Être concis
  2. Fournit des machines de sérialisation gratuitement
  3. Prévient instanciation multiple de EntityManagerFactory sans problème de synchronisation. Cela se produit car les constructeurs d'énumération sont appelés au moment du chargement de la classe et ne peuvent pas être appelés par votre code.
  4. Garantit que EntityManager n'est pas partagé à moins qu'un programmeur fasse le choix incorrect de le faire.
public enum PersistenceUnitFactory 
{ 
    PERSISTENCE_UNIT_1("persistenceUnit1"), 
    PERSISTENCE_UNIT_2("persistenceUnit2"); 

    private final EntityManagerFactory emf; 
    /** 
    * Maps the persistence unit name to this instance of the enum. 
    * 
    * @param persistenceUnitName the name of the peristence unit in 
    *       persistence.xml 
    * 
    * @see #getPersistenceUnitName() 
    */ 
    PersistenceUnitFactory(final String persistenceUnitName) 
    { 
     emf = Persistence.createEntityManagerFactory(persistenceUnitName); 
    } 

    /** 
    * Creates a new {@link EntityManager}. NEVER share this across threads. 
    * 
    * @return a new {@link EntityManager} 
    */ 
    EntityManager createEntityManager() 
    { 
     return emf.createEntityManager(); 
    } 
} 

Ensuite, il est aussi simple que de demander un EntityManager ...

PersistenceUnitFactory.PERSISTENCE_UNIT_1.createEntityManager(); 

Vous pouvez ajouter des unités de persistance que vous en avez besoin.