2012-06-24 4 views
26

Il solito linguaggio che vedo per la creazione del EntityManager è qualcosa di simile:diversi modi di ottenere l'EntityManager

public class BaseDao { 

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

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

allora è usato in questo modo:

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

domanda è perché non farlo in questo modo:

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; 
    } 
} 

In altre parole, è necessario ottenere sempre il gestore di entità tramite factory.crea teEntityManager()? o può essere creato come variabile istanza (o anche statica) e recuperato in questo modo?

Per chiarire, sto parlando di un ambiente che non utilizza contenitori EJB o Spring.

Grazie.

risposta

10

Esistono due modi per creare istanze EntityManager. Un modo è per le applicazioni SDK, e io uso molto in questo modo nei test delle unità. Questo è quello che hai nel tuo esempio:

EntityManagerFactory factory = 
    Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME); 

Nelle applicazioni Enterprise si lascia il contenitore li crea per voi e iniettare quando necessario.

EntityManager è solo un wrapper attorno a una connessione JDBC. È molto leggero e può essere creato e distrutto senza penalizzazione delle prestazioni.

Ricordare che lo EntityManager non è thread-safe, quindi se si dispone di un'istanza, potrebbe essere necessario sincronizzarne l'accesso. Vedi transaction basics per i dettagli.


Ecco come lo farei (approssimativamente):

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. 
} 

Una volta che si ottiene questo protoyped e pronto, è possibile utilizzare un DAO generico.

+0

grazie - Ho aggiunto una nota al mio post originale per chiarire che non sono in un ambiente aziendale, quindi l'iniezione del contenitore non è disponibile. Tuttavia noto il tuo commento sulla sicurezza dei thread. – jayjay

+0

RE thread-safety - Presumo che tu faccia riferimento al mio esempio, dal momento che un EntityManager iniettato e gestito da un contenitore sarebbe thread-safe. – jayjay

+0

No, non sarà thread-safe, ma il contenitore ne crea uno nuovo quando necessario (potrei sbagliarmi), quindi sembra sicuro che sia thread-safe. Se non si utilizza Enterprise Environment, non vedo alcun problema nella creazione di un'istanza statica di fabbrica EntityManagerFactory e la richiamo per ottenere istanze di EntityManager quando necessario. E non forzare a chiuderli dopo ogni transazione. Questo thread mostra un codice che può esserti utile. http://stackoverflow.com/questions/7329873/how-should-manage-database-transactions-using-entity-manager-in-a-relatively-lar – Mansour

0

Oggi dovresti probabilmente considerare a volte come spring-data e @PersistanceUnit per la gestione di EntityManager.

Un EntityManager è più di un semplice wrapper un wrapper per una connessione JDBC. Definisce l'ambito di un contesto di persistenza, che definisce l'unità di lavoro che deve essere eseguita al momento del commit di una transazione (di quando si scaricano le query sul database). All'interno di un contesto di persistenza, si garantisce anche che una determinata entità nel database genererà lo stesso oggetto Java, indipendentemente dal fatto che venga caricata direttamente o accedendola tramite una relazione OneToMany di un'altra entità.

Riguardo alla domanda iniziale relativa all'ottenimento di EntityManagerFactory in un'impostazione non a molla. È sufficiente chiamare

Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME); 

Questo metodo è un metodo factory statica, a seconda dell'implementazione JPA si sia ottenere la stessa istanza per la stessa unità di elaborazione, o un involucro poco profonda che avvolge la persistenza della sessione di fondo (di cui v'è una per PU).