2012-02-21 28 views
5

Non sto usando Spring, quindi sto creando un'istanza di EntityManager all'interno di una classe.Hibernate EntityManager, dovrebbe essere usato come un singleton?

Ho utilizzato il reverse engineering Hibernate-Eclipse per generare automaticamente le classi. Queste classi hanno tutte un'istanza di EntityManager.

Non sono sicuro al 100% di come Hibernate funzioni con EntityManager, quindi mi chiedo se è corretto che così tante istanze di questa classe (EntityManager) vengano create, ad esempio, ci saranno problemi con le transazioni?

Devo solo creare una classe separata che distribuisca un'istanza statica di un EntityManager per tutte le altre mie classi? O non importa?

EDIT: Vedo che c'è qualcosa chiamato @PersistenceContext, non sembra caricare il mio persistence.xml come bean nella variabile di istanza, questa funzione richiede primavera? (Ottengo un'eccezione di puntatore nullo, perché non è mai iniettato)

snip di codice da cui tento di usare @PersistenceContext

@PersistenceContext(unitName = "manager1") 
private EntityManager entityManager; 

mia persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" 
      version="2.0"> 
    <persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 

     <properties> 

     <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> 
     <property name="javax.persistence.jdbc.user" value="root"/> 
     <property name="javax.persistence.jdbc.password" value="mypassword"/> 
     <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost/ptbrowserdb"/> 
     <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/> 
     </properties> 
    </persistence-unit> 
</persistence> 
+0

È sufficiente rimuovere il modificatore di accesso privato (su "EntityManager") e testare? – Santosh

risposta

10

Vedere questo articolo: JPA Architecture lo spiega molto bene.

In generale è necessario un singolo Entity Manager per transazione. E questo Entity Manager non deve essere utilizzato in due transazioni allo stesso tempo.

Clairification: Voglio dire, non utilizzare un singolo Entity Manager per diverse unità di lavoro. Tipico una transazione in una sola unità di lavoro, se si dispone di diverse transazioni di un'unità di lavoro, quindi è possibile utilizzare lo stesso gestore di entità

Se si utilizza Primavera allora Primavera fare questo trattamento per voi, se si utilizza il @PersistenceContext annotazione iniettare EntityManager. Per default Spring "associa" l'EntityManager iniettato (tramite un proxy) alla transazione corrente. (E l'operazione è "legato" al thread.)

@see Spring Reference 13.5.2 Implementing DAOs based on plain JPA - contiene una paragagraph interessante dopo gli esempi di codice.

+0

lol non è necessario un singolo gestore di entità per transazione. Un gestore di entità rappresenta una sessione aperta (connessione) al database, è molto costoso solo per usarlo per una transazione. 1 sessione per operazione è considerata un antipattern! https://developer.jboss.org/wiki/Sessionsandtransactions – Maurice

+0

@Maurice: questo è un articolo interessante, ma riguarda il "vecchio" modello Session/SessionFactory di Hibernate, ma questa domanda riguarda JPA. Per quanto ne sappia, in uno dei rari argomenti in cui differiscono JPA e Hibernate-Session. Date un'occhiata al capitolo "5.1 Entity Manager and transaction scope" in https://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/transactions.html - afferma: "Un EntityManager è economico , oggetto non protetto da un thread che deve essere utilizzato una sola volta, per un singolo processo di business, una singola unità di lavoro e quindi scartato. " – Ralph

+0

e un singolo processo aziendale può consistere di più transazioni, giusto? O sei in disaccordo. Non dicono nel mio link che dovrei mettere più di una transazione in una sessione altrimenti sarebbe un antipattern? – Maurice

1

Hai bisogno di una dipendenza un'infrastruttura come Spring o Google Guice per iniettare oggetti nella tua classe altrimenti potrebbe non essere iniettato automaticamente per te.

In pratica si tratta di un'annotazione fornita da JPA che funzionerà in tandem con hibernate o qualsiasi altro framework ORM per dire ma è necessario un framework DI per iniettare gli oggetti.

Per quanto riguarda la singola istanza di gestore di entità non credo che sia necessario se si passa da Spring poiché si occupa della gestione delle istanze e delle transazioni per voi legando il proprio gestore di entità con la transazione jpa.

+1

In J2EE non è necessario alcun framework di distribuzione delle dipendenze esterno. Le iniezioni sono gestite dal contenitore. – Santosh

+0

Non hai bisogno di un framework di Dipendenza Injection: puoi farlo da solo: in un'applicazione web, ad esempio con un battistrada locale che contiene l'entity manager e un EntityManagerPerRequestPatternFilter – Ralph

+0

@Ralph - Sì, sono d'accordo che possiamo fare l'iniezione da soli ma per evitare il sovraccarico abbiamo framework comprovati per DI..spring o guice lo faremo senza problemi per noi .. a parte questi dovrebbero essere parte dello stack di applicazioni .. – raddykrish

Problemi correlati