Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Continua em execução mesmo com erro de duplicate

Olá, Acontece no vídeo da aula e comigo testando em casa também. Mesmo após ocorrer o erro de duplicate key na tabela cliente, ele continua como se estivesse em execução. Só finalizando ao clicar em Terminate. É assim mesmo, ou existe alguma maneira de tratar ?

4 respostas

Oi Marco!

para a aplicação encerrar teria que chamar o close() do EntityManagerFactory que hoje nós estamos criando em uma outra classe. Mas se estivessemos criando no método main, ficaria algo parecido com:

main(...) {

    // cria os objetos

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("financas");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();
        // faz as operações
        em.getTransaction().commit();
        em.close(); // fecha o em
        emf.close(); // fecha o emf
}

Aí o programa encerraria. Na prática, em um ambiente de um servidor de aplicação ou um servlet container (Wildfly, Jboss, Tomcat), vamos ter bibliotecas que irão gerenciar essa criação e também chamar o close() desses caras pra gente.

Mas o EntityManagerFactory, normalmente só queremos ter uma pro aplicação mesmo. :)

Faz sentido? Abraço!

Olá Lucas Félix.

Testei o que você demonstrou, mas infelizmente não é o que está acontecendo. Parece que o programa fica travado / lock no x.persist() ao receber o erro :

java.sql.SQLIntegrityConstraintViolationException: integrity constraint violation: unique constraint or index violation;

Estou fazendo o exercício de inserir dois Clientes com a mesma Conta. Segue abaixo as classe de cliente e a de conta e a de teste :

@Entity
public class Cliente {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

    private String nome;
    private String profissao;
    private String endereco;
    @JoinColumn(unique=true)
    @OneToOne
    private Conta conta;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getNome() {
        return nome;
    }
    public void setNome(String nome) {
        this.nome = nome;
    }
    public String getProfissao() {
        return profissao;
    }
    public void setProfissao(String profissao) {
        this.profissao = profissao;
    }
    public String getEndereco() {
        return endereco;
    }
    public void setEndereco(String endereco) {
        this.endereco = endereco;
    }
    public void setConta(Conta conta) {
        this.conta = conta;
    }

}

Classe Conta

@Entity
public class Conta {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;
    private String titular;
    private String banco;
    private String agencia;
    private String numero;

    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getTitular() {
        return titular;
    }
    public void setTitular(String titular) {
        this.titular = titular;
    }
    public String getBanco() {
        return banco;
    }
    public void setBanco(String banco) {
        this.banco = banco;
    }
    public String getAgencia() {
        return agencia;
    }
    public void setAgencia(String agencia) {
        this.agencia = agencia;
    }
    public String getNumero() {
        return numero;
    }
    public void setNumero(String numero) {
        this.numero = numero;
    }
}

Testa inserir cliente com mesma conta, violando a unique key.

public class TestaContaCliente {

    public static void main(String[] args) {

        Cliente cliente = new Cliente();
        cliente.setNome("Leonardo");
        cliente.setEndereco("Rua Fulano, 123");
        cliente.setProfissao("Professor");

        Cliente cliente2 = new Cliente();
        cliente2.setNome("Douglas");
        cliente2.setEndereco("Rua Fulano, 234");
        cliente2.setProfissao("Artista");

        Conta conta = new Conta();
        conta.setId(2); //esta conta existe na tabela de Conta

        cliente.setConta(conta);
        cliente2.setConta(conta);

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("financas");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        em.persist(cliente);
        em.persist(cliente2); //parece que fica travado neste comando
        System.out.println("persist"); // esta msg nao aparece no console

        em.getTransaction().commit();

        em.close();
        emf.close();
    }
}

E após recriar a tabela Cliente no banco, ela possui, uma Unique Key para o Id da Conta com isso não permitindo a inserção de 2 clientes com a mesma conta.

E ao testar o programa que simula esta situação, acredito que quando o banco devolve o erro para o programa, ele não finaliza,ele mostra o erro no console, e permanece em execução ou esperando algo, só finalizando quando clico no Terminate.

É assim mesmo, ou tem algum outro jeito de tratar / finalizar ?

Espero ter conseguido explicar.

Obrigado
solução!

Oi Marco!

Entendi o que quis dizer. Quando a exceção ocorre ele não consegue chegar nas linhas que fecham o EM e o EMF.

Você pode por o código em um bloco try-finally, já que o finally será sempre executado, mesmo que um erro ocorra. Ficaria mais ou menos assim:

public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("tarefas");
    EntityManager em = emf.createEntityManager();

    try {

    // criação dos clientes  e conta

        em.getTransaction().begin();
        em.persist(cliente);
        em.persist(cliente2);
        em.getTransaction().commit();
    } finally {
        em.close();
        emf.close();
    }
}

Tenta aí e vê se funciona? Abraço!

Boa noite Lucas.

Perfeito, funcionou.

Muito obrigado. Abs