4.1 Transações e integridade do banco de dados

O modo normal de operação de um banco de dados é quando ele recebe milhares de solicitações a cada minuto de centenas de clientes diferentes. Nesse caso, muitas vezes surgem situações em que os mesmos dados são acessados ​​a partir de diferentes consultas.

Com menos frequência, mas, novamente, de vez em quando, há situações em que uma solicitação lê uma determinada linha e outra solicitação a altera ao mesmo tempo. Imagine o que acontece se alguém ler uma linha que foi alterada apenas pela metade? Nada bom.

Este problema é resolvido de várias maneiras. Primeiro, você pode apenas bloquear a linha que muda. Tanto para ler quanto para escrever. Este método funciona, mas a velocidade da base sofre muito.

A segunda maneira é bloquear a string apenas para gravação. No entanto, ainda haverá um problema quando alguém tentar ler a linha parcialmente modificada. Conclusão - não deve haver uma situação em que a linha seja parcialmente alterada.

Portanto, eles criaram um terceiro método - transações. Uma transação é um grupo de ações que são executadas todas juntas ou nenhuma. Não pode haver uma situação em que parte das ações foi executada e a segunda parte não. Se não for possível fazer todas as alterações, todas as alterações já feitas serão revertidas.

Qualquer servidor SQL moderno permite alterar dados apenas em transações. Você abre uma transação, faz alterações em qualquer número de tabelas e confirma a transação. SQL Server, em seguida, tenta fazer alterações. Se tudo estiver bem, eles serão adicionados ao banco de dados geral. Se houver problemas, todas as alterações serão canceladas.

O Hibernate também usa esse paradigma. É por isso que na aula anterior vimos que ao tentar salvar o objeto Funcionário no banco de dados, primeiro era aberta uma transação e, após salvar, ela era confirmada.

Entraremos neste tópico com mais detalhes, mas, por enquanto, apenas saiba por que as transações são necessárias e onde elas geralmente são usadas.

4.2 Obtendo objetos

Se o Hibernate executa uma solicitação para obter dados, não há necessidade de abrir explicitamente uma transação. O próprio Hibernate fará isso se achar conveniente: ele tem suas configurações, assim como as configurações do servidor SQL.

Analisaremos como trabalhar com o banco de dados. E a mais simples delas é pegar um objeto pelo seu ID . Para fazer isso, use o método get()no objeto de sessão . A forma geral de tal solicitação:

Class Name = session.get(Class.class, ID);

Exemplo:

public User getUserById(Integer id) {
    try (Session session = sessionFactory.openSession()) {
        User user = session.get(User.class, id);
        return user;
    }
}

4.3 Salvando (adicionando) objetos

Se você deseja salvar seu objeto no banco de dados, uma consulta será executada no nível SQLINSERIR. Portanto, suas ações devem ser executadas como uma transação separada. Além disso, é melhor usar o método persist()do objeto de sessão para persistência .

A forma geral de tal solicitação:

session.persist(An object);

O método persist()altera não só a base, mas também o próprio objeto. O problema é que, quando adicionamos um objeto ao banco de dados, esse objeto ainda não possui seu próprio ID antes de adicioná-lo . Bem, geralmente sim, embora haja nuances. E depois de adicionar o objeto já tem um ID .

public boolean saveUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.persist(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

O objeto Session também possui um método save()que executa uma função semelhante. Só que o método save()é o antigo padrão do Hibernate e o método persist()é o padrão JPA.

4.4 Excluindo objetos

Se você deseja excluir um objeto existente, é muito fácil fazê-lo. Para fazer isso, o objeto de sessão possui um método especial - remove().

A forma geral de tal solicitação:

session.remove(An object);

E, claro, vamos escrever o código com um exemplo:

public boolean removeUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.remove(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

Por que é tão difícil, você pergunta?

Bem, em primeiro lugar, quaisquer alterações no banco de dados sempre têm consequências diferentes e nem sempre óbvias. Em segundo lugar, esse objeto pode ter objetos filho associados a ele etc. Portanto, os cenários de exclusão geralmente não são triviais.