1
resposta

Porque não incluído dois registros em sequencia?

Boa Tarde

Eu fiz um teste mapeando mais um item na classe movimentação para fazer 2 inserções. Porém ao fazer o select na tabela o que ocorreu é que foi feito um insert e um update.

Tentei até mesmo, após o commit do primeiro registro, realizar uma nova consulta da conta, mas não funcionou.

Entendo que são transações diferentes. Não deveria funcionar?

Obrigado.

package br.com.alura.jpa.testes;

import br.com.alura.jpa.modelo.Conta;
import br.com.alura.jpa.modelo.Movimentacao;
import br.com.alura.jpa.modelo.TipoMovimentacao;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.math.BigDecimal;
import java.time.LocalDateTime;

public class TesteMovimentacao {

    public static void main(String[] args) {

        EntityManagerFactory emf = Persistence.createEntityManagerFactory("contas");
        EntityManager em = emf.createEntityManager();

        Conta conta = em.find(Conta.class, 4L);

        System.out.println("Conta nº: " + conta.getId() + " - " + conta.getTitular());
        Movimentacao movimentacao = new Movimentacao();

        movimentacao.setDataMovimentacao(LocalDateTime.now());
        movimentacao.setDescricao("Churrascaria");
        movimentacao.setTipoMovimentacao(TipoMovimentacao.ENTRADA);
        movimentacao.setValor(new BigDecimal(240.0));
        movimentacao.setConta(conta);

        em.getTransaction().begin();
        em.persist(movimentacao);
        em.getTransaction().commit();

    // Nova consulta na conta

        em.find(Conta.class, 4L);

        movimentacao.setDataMovimentacao(LocalDateTime.now());
        movimentacao.setDescricao("Combustível");
        movimentacao.setTipoMovimentacao(TipoMovimentacao.SAIDA);
        movimentacao.setValor(new BigDecimal(1500.0));
        movimentacao.setConta(conta);

        em.getTransaction().begin();
        em.persist(movimentacao);
        em.getTransaction().commit();
        em.close();
        emf.close();

    }
}
1 resposta

Olá Lilian, como vai?

Então, é uma nova transação, mas quando fazemos o persist o estado da movimentação vai para managed então mesmo numa outra transação, o EntityManager irá ver que esse objeto está na pool de objetos controlado por ele, e dessa forma, ao invés de fazer a inserção vai fazer o update, para checar isso podemos fazer o seguinte:

em.getTransaction().commit();

System.out.println("Temos a movimentação ->" + em.contains(movimentacao));

>> Temos a movimentação ->true

A mesma coisa acontece para o segundo find que você fez, após o primeiro a JPA guarda na pool, se você pedir de novo eles apontaram para o mesmo objeto

Conta conta = em.find(Conta.class, 4L);
[... seu código...]

// Mesmo sem implementar o equals:

var contaNovamente = em.find(Conta.class, 4L);

System.out.println("São Iguais: -> "+ conta.equals(contaNovamente));
--> True

Então quando você fez a segunda operação eles já estavam interconectados, e ele realmente só irá fazer o update :)

O que poderíamos fazer seria um em.close() mas o cachê acusaria que está tentando persistir um objeto no estado detached e não um objeto new

Neste caso o que teria que ser feito seria criar uma nova movimentação para esse objeto ter o estado de new mesmo :)

Abraços e Bons Estudos!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software