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

Quando eu vou dar update num dado ele cria um nova linha, faz o update e salva no banco

Olá pessoal! Estou usando MySql pra acompanhar esse curso, porém, quando eu sigo as instruções pra dar um update numa linha, ele acaba criando uma novo registro, estou acompanhando as tabelas usando o MySQL Workbench. No console do IntelliJ ele mostra que esta inserindo uma linha e fazendo um update, assim como na vídeo aula. Eu queria dizer pra JPA que se o registro já existir n crie um novo. No caso o JPA deveria fazer só um select e update, mas não é oq esta acontecendo. Será que é alguma configuração do persistence.xml?

package br.com.alura.loja.testes;

import br.com.alura.loja.br.com.alura.util.JPAUtilMySql;
import br.com.alura.loja.modelo.Categoria;
import javax.persistence.EntityManager;
import java.math.BigDecimal;

public class Teste {
    public static void main(String[] args) {
        Categoria categoria = new Categoria("CELULARES");

        EntityManager em = JPAUtilMySql.getEntityManager();

        em.getTransaction().begin();
        em.persist(categoria);
        categoria.setNome("1234");
        em.getTransaction().commit();
        em.close();
    }
}

Aqui ta o meu persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
             xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">

    <persistence-unit name="loja" transaction-type="RESOURCE_LOCAL">
        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:loja"/>
            <property name="javax.persistence.jdbc.user" value="sa"/>
            <property name="javax.persistence.jdbc.password" value=""/>

            <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>

    <!-- UNIDADE DE TESTES -->
    <persistence-unit name="loja-mysql">
        <properties>
            <!-- DADOS CONEXAO -->
            <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
            <property name="hibernate.connection.username" value="root" />
            <property name="hibernate.connection.password" value="root" />
            <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/loja" />
            <property name="hibernate.default_schema" value="loja"/>

            <!-- CONFIGURACAO -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
            <property name="hibernate.archive.autodetection" value="class" />

        </properties>
    </persistence-unit>
</persistence>
4 respostas

Oi, Você precisa consultar primeiro no banco. Categoria possui um id, troque o persist por find, passando o id desejado:

    Categoria encontrada = em.find(Categoria.class, 1L);
        System.out.println(encontrada.getNome());

Quando você usa o H2, por ele estar em memória, quando você finaliza a execução ele é deletado de lá. Quando usa algum outro standalone ele continua na memória da máquina. No trecho:

em.getTransaction().begin();
em.persist(categoria);
...

Na parte destacada, você está realizando um INSERT ( em.persist(categoria) ) então sim um novo registro será criado. Para fazer a checagem se aquele produto existe, você deve utilizar lógica de programação, já que todo insert gera um ID novo.

Oi Rodrigo,

No seu código você está criando um novo objeto categoria(ou seja, ela nunca esteve no banco de dados e está no estado transient), por isso quando você chamar o método em.persist a JPA vai inserir o registro no banco de dados. Isso é independente do banco de dados.

Logo na sequencia você chama o método setNome("1234") e por isso a JPA vai realizar um update para atualizar o nome da categoria que acabou de ser inserida.

Bons estudos!

solução!

Oi, pessoal! Obrigado pelas respostas. Eu me expressei meio mal na pergunta tbm, oq eu queria fazer era alterar um dado existente no BD. Vendo agora eu analisei e vi que era uma confusão que eu fiz com as referências, apesar dessa categoria CELULARES ser a mesma no meu banco de dados que possui id 1, não é a mesma referência que está no banco.

Categoria categoria = new Categoria("CELULARES");

Como foi citado pelos colegas eu busquei essa referencia no banco com o find(), setei o valor dei um merge() pra trazer essa referência ao estado Managed e deu tudo certo, consegui o resultado que eu queria.

        em.getTransaction().begin();
        Categoria id1 = find(Categoria.class, 1l);
        id1.setNome("1234");
        em.merge(id1);
        em.getTransaction().commit();
        em.close();

Obrigado a todos!