4.1 Introduzione alle transazioni in Hibernate

A tutto quanto sopra, vorrei aggiungere informazioni sulle transazioni. Come già saprai, una transazione è un insieme di azioni che devono essere eseguite solo tutte insieme . Se un'azione non è riuscita o è stata eseguita con un errore, tutte le altre azioni devono essere annullate.

Hibernate è in grado di lavorare con due tipi di transazioni:

  • JDB
  • JTA

Una transazione JDBC è in realtà una transazione di database. È legato al lavoro con il database, alla connessione JDBC. E si assicura che le azioni quando si lavora con il database vengano eseguite come dovrebbero: tutto o niente.

JTA - La transazione è una transazione a livello di applicazione. Non è legato a nessun database. Il suo compito è garantire che vengano eseguite determinate azioni: tutto o niente.

Ad esempio, è possibile scrivere dati su diversi database all'interno di una singola transazione JTA. Quindi, se si verifica un errore, la transazione JTA dovrà eseguire il rollback delle modifiche in tutti i database. Anche quelli che sono stati eseguiti con successo in termini di un particolare database.

4.2 Interfaccia transazioni di ibernazione

Nella libreria di Hibernate, una transazione è rappresentata dall'interfaccia Transaction, che può avere diverse implementazioni. Ad esempio, quando si lavora con Spring, Spring fornisce il proprio meccanismo di transazione JTA.

I metodi di questa interfaccia sono:

# Metodo Descrizione
1 inizio() Avvia una nuova transazione
2 commettere() Termina la transazione, invia/commette tutte le modifiche
3 rollback() Esegue il rollback della transazione corrente
4 setTimeout(int secondi) Imposta il tempo massimo di esecuzione della transazione
5 è attivo() Controlla se una transazione è attiva o meno
6 wasRolledBack() Controlla se la transazione è stata ripristinata normalmente
7 wasCommitted() Controlla se la transazione ha eseguito il commit normalmente
8 registroSincronizzazione() Registra una richiamata per controllare la transazione

Importante! La creazione di un oggetto di transazione e l'avvio di una transazione sono due cose diverse. Qui puoi tracciare un'analogia con la classe Thread. Quando crei un oggetto Thread(), la JVM non avvia ancora un nuovo thread. Per avviarlo, è necessario chiamare il metodo start() sull'oggetto Thread. È lo stesso con una transazione: deve chiamare il metodo begin().

Un esempio di come le transazioni vengono generalmente gestite in Hibernate:


Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
try {
    transaction.begin();
    Long count = session.createQuery("select count(*) from Employee", Long.class).uniqueResult();
    transaction.commit();
}
catch (Exception e) {
	if (transaction.getStatus() == ACTIVE || transaction.getStatus() == MARKED_ROLLBACK) {
    transaction.rollback();
    }
}
finally {
	session.close();
	sessionFactory.close();
}

Vediamo tre cose qui:

Innanzitutto, tutto il lavoro con il database viene racchiuso in una transazione chiamando metodi begin()e commit()Tutte le azioni tra le chiamate a questi due metodi devono essere eseguite: tutte insieme o niente.

In secondo luogo, se si verifica un errore, proviamo a eseguire il rollback della transazione, chiamando il metodo rollback(). Ciò significa che TransactionManger deve prima registrare tutte le azioni comprese tra begin()e commit(), quindi restituire tutto com'era se abbiamo chiamato rollback().

E a proposito, non è un dato di fatto che non ci saranno errori quando si chiama il metodo rollback. Gli errori accadono sempre. Devi solo accettare questo fatto ed essere pronto per questo.

4.3 Gestore delle transazioni

Dal punto di vista della gestione delle transazioni, Hibernate è solo un wrapper di oggetti leggero per JDBC. Hibernate stesso non ha funzionalità di elaborazione delle transazioni. Hibernate Transaction è in realtà un wrapper per la transazione JDBC sottostante (o wrapper per transazioni JTA). JDBCTransaction è l'impostazione predefinita. Esempio dal file delle impostazioni di Hiberante:


hibernate.transaction.factory_class  org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.factory_class  org.hibernate.transaction.JDBCTransactionFactory

Diamo un'altra occhiata al nostro codice usando le transazioni:


Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
transaction.begin();
//here is your code for working with the base
session.flush();
transaction.commit();
session.close();

Ora diamo un'occhiata al codice della classe JDBCTransaction:


public class JDBCTransaction implements Transaction {
 
    public void begin() throws HibernateException {
    	...
    	if (toggleAutoCommit) jdbcContext.connection().setAutoCommit(false);
    	...
    }
}

Questo è il metodo per avviare una transazione. Quindi guarda il metodo di invio:


public void commit() throws HibernateException {
    ...
    jdbcContext.connection().commit();
    ...
    jdbcContext.connection().setAutoCommit( true );
    ...
}

Ora sostituiamo questo codice nel codice di esempio di Hibernate:

Ibernazione Codice JDBC semplice

Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
transaction.begin();
//here is your code for working with the database
session.flush();
transaction.commit();
session.close();

Connection conn = jdbcContext.connection();
conn.setAutoCommit(false);
 
//here is your database code
conn.commit ()
conn.setAutoCommit(true);
conn.close();

Quindi le transazioni Hibernate native sono solo chiamate JDBC native al database. Niente di più e niente di meno. Ma le transazioni JTA sono più interessanti. Ma ne riparleremo un'altra volta.