4.1 Inleiding tot transacties in Hibernate

Aan al het bovenstaande wil ik informatie over transacties toevoegen. Zoals u al weet, is een transactie een groep acties die alleen samen moeten worden uitgevoerd . Als een actie is mislukt of met een fout is uitgevoerd, moeten alle andere acties worden geannuleerd.

Hibernate kan met twee soorten transacties werken:

  • JDBC
  • JTA

Een JDBC-transactie is eigenlijk een databasetransactie. Het is gekoppeld aan het werken met de database, aan de JDBC-verbinding. En hij zorgt ervoor dat de acties bij het werken met de database worden uitgevoerd zoals het hoort: alles of niets.

JTA - Transactie is een transactie op applicatieniveau. Het is niet gebonden aan een database. Zijn taak is ervoor te zorgen dat bepaalde acties worden uitgevoerd: alles of niets.

U kunt bijvoorbeeld binnen één JTA-transactie gegevens naar verschillende databases schrijven. Als er dan een fout optreedt, moet de JTA-transactie de wijzigingen in alle databases ongedaan maken. Zelfs degenen die met succes zijn uitgevoerd in termen van een bepaalde database.

4.2 Transactie-interface in slaapstand zetten

In de Hibernate-bibliotheek wordt een transactie vertegenwoordigd door de transactie-interface, die verschillende implementaties kan hebben. Als u bijvoorbeeld met Spring werkt, biedt Spring zijn eigen JTA-transactiemechanisme.

De methoden van deze interface zijn:

# Methode Beschrijving
1 beginnen() Start een nieuwe transactie
2 verbinden() Beëindigt transactie, pusht/committeert alle wijzigingen
3 terugrollen() Draait de huidige transactie terug
4 setTimeout(int seconden) Stelt de maximale uitvoeringstijd van de transactie in
5 is actief() Controleert of een transactie actief is of niet
6 wasRolledBack() Controleert of de transactie normaal is teruggedraaid
7 was toegewijd() Controleert of de transactie normaal is uitgevoerd
8 registerSynchronisatie() Registreert een callback om de transactie te controleren

Belangrijk! Een transactieobject maken en een transactie starten zijn twee verschillende dingen. Hier kun je een analogie tekenen met de klasse Thread. Wanneer u een Thread()-object maakt, start de JVM nog geen nieuwe thread. Om het te starten, moet u de methode start() op het object Thread aanroepen. Hetzelfde geldt voor een transactie - deze moet de methode begin() aanroepen.

Een voorbeeld van hoe transacties gewoonlijk worden afgehandeld 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();
}

We zien hier drie dingen:

Ten eerste wordt al het werk met de database verpakt in een transactie door methodes aan te roepen begin()en commit()alle acties tussen aanroepen naar deze twee methoden moeten worden uitgevoerd: ofwel allemaal tegelijk, ofwel niets.

Ten tweede, als er een fout optreedt, proberen we de transactie terug te draaien - bel het rollback(). Dit betekent dat TransactionManger eerst alle acties tussen begin()en moet vastleggen commit()en dan alles moet teruggeven zoals het was als we belden rollback().

En trouwens, het is geen feit dat er geen fout zal zijn bij het aanroepen van de rollback-methode. Fouten gebeuren altijd. Je hoeft dit feit alleen maar te accepteren en er klaar voor te zijn.

4.3 Transactiebeheerder

Vanuit het perspectief van transactiebeheer is Hibernate slechts een lichtgewicht objectverpakking voor JDBC. Hibernate zelf heeft geen functies voor transactieverwerking. Hibernate Transaction is eigenlijk een wrapper voor de onderliggende JDBC-transactie (of JTA-transactiewrapper). JDBCTransaction is de standaardinstelling. Voorbeeld uit het Hiberante-instellingenbestand:


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

Laten we onze code nog eens bekijken met behulp van transacties:


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();

Laten we nu eens kijken naar de JDBCTransaction-klassecode:


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

Dit is de methode om een ​​transactie te starten. Kijk dan naar de verzendmethode:


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

Laten we nu deze code vervangen door de Hibernate-voorbeeldcode:

Overwinteren Eenvoudige JDBC-code

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();

Native Hibernate-transacties zijn dus alleen native JDBC-oproepen naar de database. Niets meer en niets minder. Maar JTA-transacties zijn interessanter. Maar daarover een andere keer meer.