2013-02-15 7 views
21

se si dispone di più thread, ciascuno utilizza injector per ottenere l'oggetto EntityManager, ciascuno utilizza l'oggetto em per selezionare un elenco di altri oggetti classe. Pronto per essere utilizzato in un ciclo for.JAVA: un oggetto EntityManager in un ambiente multithread

Se un thread termina per primo e chiama clear(), ciò influirà sugli altri thread? Come il ciclo for avrà un'eccezione?

Che ne dici di close()?

Se la risposta è "Dipende", che cosa (definizione di classe? Chiamata di metodo?) E dove (codice java? Annotazione? Xml?) Dovrei guardare per scoprire come è dipeso?

Non ho scritto la fonte, sto solo usando la libreria di qualcun altro senza documentazione.

Grazie.

+0

È possibile fornire dettagli sul meccanismo dell'iniettore e su come è l'istanza di EntityManager. Ad esempio, un'applicazione Spring. Stai utilizzando OpenEntityManagerInViewFilter? – Rohit

+0

Sì, certo. La stessa istanza/oggetto EntityManager sta passando in giro nella libreria, ma non vedo alcuna funzione pubblica per ottenerla. Così ho usato il com.google.inject.Injector per ottenere l'istanza di usarlo nelle mie funzioni. – user1589188

risposta

4

Esistono due tipi di gestione di EntityManager: contenitore gestito e gestione dell'applicazione. Per l'applicazione gestita, il metodo preferito per ottenere EntityManager è tramite EntityManagerFactory. tutorial di Java EE dice questo:

Container-Managed Entity gestori

Con un contenitore gestiti entità manager, contesto di persistenza di un'istanza EntityManager è propagato automaticamente dal contenitore per tutte le applicazioni componenti che utilizzano il Istanza EntityManager all'interno di una singola transazione Java Transaction API (JTA).

Le transazioni JTA di solito coinvolgono le chiamate tra i componenti dell'applicazione. Per completare una transazione JTA, questi componenti in genere richiedono l'accesso a un singolo contesto di persistenza. Ciò si verifica quando un EntityManager è iniettato nei componenti dell'applicazione mediante l'annotazione javax.persistence.PersistenceContext . Il contesto di persistenza viene propagata automaticamente con l'attuale transazione JTA, e riferimenti EntityManager mappati alla stessa unità di persistenza fornire l'accesso al contesto di persistenza all'interno di tale transazione. Propagando automaticamente il contesto di persistenza, i componenti dell'applicazione non devono passare i riferimenti alle istanze di EntityManager l'un l'altro per apportare modifiche all'interno di una singola transazione . Il contenitore Java EE gestisce il ciclo di vita dei gestori di entità gestite dal contenitore .

per ottenere un'istanza EntityManager, iniettare il gestore entità nella componente dell'applicazione:

@PersistenceContext 
EntityManager em; 

Applicazione gestiti Entity Gestori

Con un gestore di entità un'applicazione gestiti, d'altra mano, il contesto di persistenza non viene propagato ai componenti dell'applicazione e il ciclo di vita delle istanze EntityManager è gestito dall'applicazione .

gestori di entità applicativi gestiti vengono utilizzati quando le applicazioni devono accesso un contesto di persistenza che non si propaga con la transazione JTA tra le istanze EntityManager in un particolare persistenza unità. In questo caso, ogni EntityManager crea un nuovo contesto di persistenza isolato. EntityManager e il suo contesto di persistenza associato vengono creati e distrutti esplicitamente dall'applicazione. Vengono inoltre utilizzati quando le istanze di EntityManager non possono essere immesse direttamente perché le istanze di EntityManager non sono thread-safe. Le istanze EntityManagerFactory sono thread-safe.

http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html

+0

Grazie. Quindi capisco che ci sono due tipi. Quindi, come posso sapere quale tipo sta utilizzando la libreria? – user1589188

+0

Leggere il codice sorgente della biblioteca/consultare il fornitore? – gerrytan

9

gestori di entità non sono thread-safe (fonte Java EE 6 tutorial) e non possono essere condivise tra thread. Ogni thread deve utilizzare il proprio gestore di entità o accadranno cose brutte, indipendentemente dalle chiamate clear() o close().

Tuttavia, se l'iniettore sta iniettando ogni thread con il proprio gestore di entità, le cose dovrebbero andare bene.

primavera ed eventualmente altri quadri DI inietterà un proxy ThreadLocal-based per un vero e proprio gestore di entità nei vostri fagioli. Le chiamate effettuate da ciascun thread fungono da proxy per l'istanza locale thread-reale di un gestore di entità: questo è il modo in cui le cose possono funzionare anche se potrebbe sembrare che un gestore di entità sia condiviso tra più thread.

Maggiori dettagli sul modo in cui il gestore di entità viene iniettato aiuterebbe (primavera, ecc)

+0

Grazie! Mi piacerebbe assistere il tuo aiuto. Ho trovato guizzi nella biblioteca, se questo è collegato. Altrimenti, per favore dimmi come trovare ciò che vuoi sapere. – user1589188

+1

"Ogni thread deve utilizzare il proprio gestore di entità o accadranno cose brutte." cosa potrebbe andare storto, per favore, puoi elaborare. – eatSleepCode

1

È normalmente hanno le transazioni in tutto quello che fai con gli oggetti di database. Ciò che ciascun thread dato vede sulle modifiche apportate da altri thread è controllato dalle impostazioni di "isolamento della transazione".

Iniziare a conoscere le diverse impostazioni di isolamento e applicare le impostazioni corrette in base alle proprie esigenze. C'è un compromesso tra precisione e velocità. http://en.wikipedia.org/wiki/Isolation_%28database_systems%29

27

Qui funziona pieno thread-safe Entity Manager Helper.

import javax.persistence.EntityManager; 
import javax.persistence.EntityManagerFactory; 
import javax.persistence.Persistence; 

public class EntityManagerHelper { 

    private static final EntityManagerFactory emf; 
    private static final ThreadLocal<EntityManager> threadLocal; 

    static { 
     emf = Persistence.createEntityManagerFactory("Persistent_Name"); 
     threadLocal = new ThreadLocal<EntityManager>(); 
    } 

    public static EntityManager getEntityManager() { 
     EntityManager em = threadLocal.get(); 

     if (em == null) { 
      em = emf.createEntityManager(); 
      // set your flush mode here 
      threadLocal.set(em); 
     } 
     return em; 
    } 

    public static void closeEntityManager() { 
     EntityManager em = threadLocal.get(); 
     if (em != null) { 
      em.close(); 
      threadLocal.set(null); 
     } 
    } 

    public static void closeEntityManagerFactory() { 
     emf.close(); 
    } 

    public static void beginTransaction() { 
     getEntityManager().getTransaction().begin(); 
    } 

    public static void rollback() { 
     getEntityManager().getTransaction().rollback(); 
    } 

    public static void commit() { 
     getEntityManager().getTransaction().commit(); 
    } 
} 
+0

Un semplice esempio su come utilizzare questo helper in un'applicazione multithread sarebbe fantastico. :) –

0

Sono fuori da tre anni o giù di lì :), ma per quanto riguarda l'iniezione di EntityManager in EJB è interessato, ecco un link al blog di Adam Bien http://www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected

copia-incolla da lì:

"è possibile iniettare direttamente nel EntityManager EJB Ma. è thread-safe ?:

@Stateless 
public class BookServiceBean implements BookService { 


    @PersistenceContext EntityManager em; 

    public void create(Book book) { this.em.persist(book);} 

} 

"

e la risposta è, ancora una volta copia-incolla:

"Lavorare con EJB senza alcuna ulteriore configurazione è thread-safe indipendentemente dal fatto che si stia invocando un metodo o più metodi contemporaneamente. Il contenitore si occupa della serializzazione delle chiamate. ",

che forse potrebbe essere più chiaro, ma implica che è possibile iniettare EntityManager in bean di sessione stateless e non essere preoccupato dai problemi di concorrenza di EntityManager.