2013-05-31 14 views
5

Nella nostra applicazione utilizziamo Spring e Hibernate.Iniettare oggetto Session su bean DAO anziché Session Factory?

In tutte le classi DAO abbiamo cablato SessionFactory e ognuno dei metodi DAO chiama il metodo getCurrentSession().

Domanda: ho perché non iniettiamo oggetto Session invece di oggetto SessionFactory in ambito prototipo? Questo ci salverà la chiamata a getCurrentSession.

Penso che il primo metodo sia corretto ma alla ricerca di scenari concreti in cui il secondo metodo genererà errori o potrebbe avere cattive prestazioni?

+0

Un caso ha letto [il documento] (http://docs.jboss.org/hibernate/orm/3.5/javadoc/org/hibernate/Session.html) che dice 'Se la Sessione genera un'eccezione, la transazione deve essere ritirato e la sessione scartata. Lo stato interno della sessione potrebbe non essere coerente con il database dopo che si è verificata l'eccezione. –

+0

È meglio iniettare 'javax.persistence.EntityManager', ma per questo, è necessario insistere sull'uso di JPA. – Lion

risposta

3

Quando si definisce un bean come ambito prototipo viene creata una nuova istanza per ciascun luogo in cui deve essere iniettata. Quindi ogni DAO otterrà una diversa istanza di Session, ma tutte le invocazioni dei metodi sul DAO finiranno per utilizzare la stessa sessione. Poiché la sessione non è thread-safe, non dovrebbe essere condivisa su più thread, questo sarà un problema.

Per la maggior parte delle situazioni, la sessione deve essere l'ambito della transazione, ad esempio una nuova sessione viene aperta all'avvio della transazione e quindi viene chiusa automaticamente al termine della transazione. In alcuni casi potrebbe essere necessario estenderlo per richiedere l'ambito.

Se si desidera evitare l'uso di SessionFactory.currentSession, è necessario definire la propria implementazione dell'ambito per ottenere ciò.

Questo è qualcosa che è già implementato per JPA utilizzando i proxy. In caso di JPA EntityManager viene iniettato invece di EntityManagerFactory. Invece di @Autowired c'è una nuova annotazione @PersistenceContext. Un proxy viene creato e iniettato durante l'inizializzazione. Quando viene invocato un metodo, il proxy acquisirà l'implementazione effettiva di EntityManager (utilizzando qualcosa di simile a SessionFactory.getCurrentSession) e delegherà ad essa.

La stessa cosa può essere implementata anche per Hibernate, ma la complessità aggiuntiva non ne vale la pena. È molto più semplice definire un metodo getSession in un BaseDAO che chiama internamente SessionFactory.getCurrentSession(). Con questo il codice che utilizza la sessione è identico alla sessione di iniezione.

3

Iniettando le sessioni di prototipo significa che ognuno dei tuoi oggetti DAO, per definizione, otterrà la propria sessione ... D'altra parte SessionFactory ti dà il potere di open e condividi sessioni a volontà.

Infatti getCurrentSession non si apre una nuova sessione su ogni chiamata ... Invece, si riutilizzerà sessioni binded alla current session context (ad esempio, Filo, JTA Transacion o contesto Esternamente gestito).

Quindi pensiamoci; Supponiamo che nel tuo livello aziendale ci sia un'operazione che ha bisogno di leggere e aggiornare diverse tabelle di database (che significa interagire, direttamente o indirettamente, con diversi DAO) ... Scenario abbastanza comune giusto? Di solito, quando questo tipo di operazione fallisce, vorrai eseguire il rollback di tutto ciò che è successo nell'operazione corrente, giusto? Quindi, per questo caso "particolare", quale tipo di strategia sembra appropriata?

  1. Spanning diverse sessioni, ognuna delle quali gestisce il proprio tipo di oggetti e legato a diverse transazioni.
  2. Avere una singola sessione di gestione degli oggetti relativi a questa operazione ... Delimitare le transazioni in base alle esigenze aziendali.

In breve, condividere le sessioni e delimitare le transazioni in modo efficace non solo migliorerà le prestazioni delle applicazioni, è parte della funzionalità dell'applicazione.

sarei profondamente consiglio di leggere Chapter 2 e Chapter 13 del Hibernate Core Reference Manual per comprendere meglio i ruoli che SessionFactory, Session e Transaction giochi nel quadro. Insegnerà inoltre circa le Unità di lavoro così come i popolari modelli di sessione e anti-pattern.