2011-12-23 15 views
6

In passato ho sviluppato alcuni elementi JPA che utilizzavano un'istanza di javax.persistence.EntityManager per istanza di DAO; questo è il modo in cui sono configurati molti esempi.JPA EntityManager Statico o Istanza?

public class BaseDaoThatEveryDaoExtends { 
    @PersistenceContext 
    private EntityManager entityManager; 
} 

Ho appena imbattuto il codice che utilizza un staticajavax.peristence.EntityManger iniettato da un PersistenceContext annotazione, l'architetto mi dice ciò non causa problemi e non hanno mai avuto alcun problema anche in un'applicazione cluster con JTA ed un XA origine dati:

public class BaseDaoThatEveryDaoExtends { 
    @PersistenceContext 
    private static EntityManager entityManager; 
} 

Per quanto posso dire questo è un anti-modello come il EntityManager detiene alcune informazioni di stato e rendere statica fa che tutta l'applicazione dello stato di larghezza. Inoltre, questo rende le classi molto difficili da testare.

Ci sono altri svantaggi a fare questo o si tratta di un modo standard di utilizzare uno EntityManager?

risposta

1

EntityManager trattiene i propri dati utilizzando un threadlocal, quindi potrebbe essere ok mantenere un riferimento statico ad esso poiché tutti i thread che lo accedono sarebbero gestiti indipendentemente. In effetti, non sarei sorpreso se il contesto EJB dovesse rimanere in EntityManager in modo statico, usando un pattern singleton.

Personalmente, non lo definirei mai in modo statico. Sembra inutile, e nel peggiore dei casi potrebbe avere alcuni effetti collaterali imprevedibili.

Un problema che posso vedere è la capacità di accedere inavvertitamente l'entityManager da un metodo statico:

public class BaseDaoThatEveryDaoExtends { 
    @PersistenceContext 
    private static EntityManager entityManager; 

    public static void doSomeStaticWork(){ 
     ... 
     entityManager.doSomething; //NPE possible! 
    } 
} 

ho potuto vedere l'EntityManager non essere iniettata e conseguente NPE in questo caso.

Oltre a ciò ci possono essere alcuni problemi relativi al testing/mocking con EntityManager.

+0

Un NPE è anche molto buono quando si costruisce manualmente un'istanza del DAO invece di ottenerlo iniettato e invoca i metodi di istanza su di esso. In modo che non sia davvero un argomento. – BalusC

+0

Tranne che non è necessario costruire il BaseDaoThatEveryends di tutti i tempi, è sufficiente chiamare BaseDaoThatEveryends.doSomeStaticwork() che presenta un NPE. –

0

EntityManagerFactory è garantito per essere thread-safe, quindi penso che questo sia il modo "corretto": Utilizzare l'EMF nelle posizioni thread-non sicure e proteggere l'EntityManger stesso da problemi di threading.

4

Penso che il maggior rischio non si trovi nello stesso EntityManager, ma nel contesto dell'applicazione che è collegato al gestore di entità quando viene utilizzato.

Supponiamo che due client diversi effettuino una richiesta al server, entrambi richiamano due metodi diversi dell'applicazione, entrambi in esecuzione su thread diversi, ma entrambi utilizzano lo stesso gestore di entità.

Per quanto ne so il gestore di entità avrà un singolo contesto collegato ad esso, questo contesto sarà condiviso da entrambi i client. Ogni volta che carichi un'istanza nel contesto, sarà disponibile per i thread attraverso il gestore di entità condivisa. Cosa accadrà se si manometteranno i dati l'uno dell'altro? Cosa succederà se utilizzano una configurazione di isolamento delle transazioni diversa ?. Come puoi essere sicuro che il client 1 non stia modificando i dati attualmente utilizzati dal client 2?

Cosa succede se uno dei client invalida il contesto, cosa farà l'altro? Come gestisci la concorrenza in questo modo?

Problemi correlati