4.1 Introdução às transações no Hibernate

A todos os itens acima, gostaria de adicionar informações sobre transações. Como você já sabe, uma transação é um grupo de ações que devem ser executadas apenas todas juntas . Se alguma ação falhou ou foi executada com erro, todas as outras ações devem ser canceladas.

O Hibernate é capaz de trabalhar com dois tipos de transações:

  • JDBC
  • JTA

Uma transação JDBC é, na verdade, uma transação de banco de dados. Está vinculado ao trabalho com o banco de dados, à conexão JDBC. E ele garante que as ações ao trabalhar com o banco de dados sejam executadas como deveriam: tudo ou nada.

JTA - A transação é uma transação no nível do aplicativo. Não está vinculado a nenhum banco de dados. Sua tarefa é garantir que certas ações sejam executadas: tudo ou nada.

Por exemplo, você pode gravar dados em vários bancos de dados diferentes em uma única transação JTA. Então, se ocorrer um erro, a transação JTA terá que reverter as alterações em todos os bancos de dados. Mesmo aqueles que foram executados com sucesso em termos de um determinado banco de dados.

4.2 Interface de Transações do Hibernate

Na biblioteca do Hibernate, uma transação é representada pela interface Transaction, que pode ter diferentes implementações. Por exemplo, ao trabalhar com Spring, Spring fornece seu próprio mecanismo de transação JTA.

Os métodos desta interface são:

# Método Descrição
1 começar() Inicia uma nova transação
2 comprometer-se() Encerra a transação, envia/confirma todas as alterações
3 reverter() Reverte a transação atual
4 setTimeout(int segundos) Define o tempo máximo de execução da transação
5 está ativo() Verifica se uma transação está ativa ou não
6 wasRolledBack() Verifica se a transação foi revertida normalmente
7 wasCommitted() Verifica se a transação foi confirmada normalmente
8 registerSynchronization() Registra um callback para controlar a transação

Importante! Criar um objeto de transação e iniciar uma transação são duas coisas diferentes. Aqui você pode fazer uma analogia com a classe Thread. Quando você cria um objeto Thread(), a JVM ainda não inicia um novo thread. Para iniciá-lo, você precisa chamar o método start() no objeto Thread. É o mesmo com uma transação - ela precisa chamar o método begin().

Um exemplo de como as transações geralmente são tratadas no 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();
}

Vemos três coisas aqui:

Primeiro, todo o trabalho com o banco de dados é agrupado em uma transação chamando métodos begin()e commit()todas as ações entre as chamadas para esses dois métodos devem ser executadas: tudo junto ou nada.

Em segundo lugar, se ocorrer algum erro, tentamos reverter a transação - chame o método rollback(). Isso significa que TransactionManger deve primeiro registrar todas as ações que ocorreram entre begin()e commit(), e depois retornar tudo como seria se chamássemos rollback().

E por falar nisso, não é fato que não haverá erro ao chamar o método de reversão. Erros sempre acontecem. Você só precisa aceitar esse fato e estar pronto para isso.

4.3 Gerenciador de transações

De uma perspectiva de gerenciamento de transações, o Hibernate é apenas um wrapper de objeto leve para JDBC. O próprio Hibernate não possui recursos de processamento de transações. Hibernate Transaction é, na verdade, um wrapper para a transação JDBC subjacente (ou wrapper de transação JTA). JDBCTransaction é o padrão. Exemplo do arquivo de configurações do Hiberante:


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

Vamos dar outra olhada em nosso código usando transações:


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

Agora vamos ver o código da classe JDBCTransaction:


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

Este é o método para iniciar uma transação. Em seguida, observe o método send:


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

Agora vamos substituir este código no código de exemplo do Hibernate:

hibernar Código JDBC Simples

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

Portanto, as transações nativas do Hibernate são apenas chamadas JDBC nativas para o banco de dados. Nada mais e nada menos. Mas as transações JTA são mais interessantes. Mas mais sobre isso outra hora.