Problema JPA - NetBeans

Estou utilizando o “Form de amostra Mestre/Detalhe”, que faz o formulário e a classe relacionado ao banco de dados automaticamente (Estou utilizando o EclipseLink JPA 2.1 como persistence) . Quando mando deletar alguma linha, ele deleta corretamente. Porém, ao inserir uma nova, ele não “atualiza” o ID, e mantem sempre a sequencia de ID, mesmo que eu tenha excluido TODOS os registros, ele nao zera o ID. Alguém poderia me Ajudar? Grato!

Banco de dados antes:


image

Mando deletar:

image

Clico em novo e preencho:
image

Ao salvar e atualizar:
image

Código JCadMedico.java:

public class JCadMedico extends JPanel {

public JCadMedico() {
    initComponents();
    if (!Beans.isDesignTime()) {
        entityManager.getTransaction().begin();
    }
}

@SuppressWarnings(“unchecked”)

@SuppressWarnings(“unchecked”)

private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {
idmedicoField.setText(" ");
entityManager.getTransaction().rollback();
entityManager.getTransaction().begin();
java.util.Collection data = query.getResultList();
for (Object entity : data) {
entityManager.refresh(entity);
}
list.clear();
list.addAll(data);
}

private void deleteButtonActionPerformed(java.awt.event.ActionEvent evt) {                                             
    int[] selected = masterTable.getSelectedRows();
    List<model.Medico> toRemove = new ArrayList<model.Medico>(selected.length);
    for (int idx = 0; idx < selected.length; idx++) {
        model.Medico m = list.get(masterTable.convertRowIndexToModel(selected[idx]));
        toRemove.add(m);
        entityManager.remove(m);
    }
     list.removeAll(toRemove);
     
    
    if(JOptionPane.showConfirmDialog(null, "Deseja realmente excluir os registros? ", "Alerta! ", JOptionPane.YES_OPTION, JOptionPane.WARNING_MESSAGE)==0){
        saveButtonActionPerformed(evt);
        
    }
    else{
        refreshButtonActionPerformed(evt);
    }
    
   
    
    
}          

private void newButtonActionPerformed(java.awt.event.ActionEvent evt) {                                          
    model.Medico m = new model.Medico();
    entityManager.persist(m);
    list.add(m);
    int row = list.size() - 1;
    masterTable.setRowSelectionInterval(row, row);
    masterTable.scrollRectToVisible(masterTable.getCellRect(row, 0, true));
    idmedicoField.setText(Integer.toString(masterTable.getRowCount()));
    System.out.println(list);
    
    
}                                         

private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {                                           
    try {
         
        entityManager.getTransaction().commit();
       
        entityManager.getTransaction().begin();
      
       
    } catch (RollbackException rex) {
        rex.printStackTrace();
         
        entityManager.getTransaction().begin();
        List<model.Medico> merged = new ArrayList<model.Medico>(list.size());
        for (model.Medico m : list) {
            merged.add(entityManager.merge(m));
        }
         
        list.clear();
        list.addAll(merged);
    }
   
}     

// Variables declaration - do not modify
private javax.swing.JTextField crmField;
private javax.swing.JLabel crmLabel;
private javax.swing.JButton deleteButton;
private javax.persistence.EntityManager entityManager;
private javax.swing.JTextField idmedicoField;
private javax.swing.JLabel idmedicoLabel;
private java.util.List<model.Medico> list;
private javax.swing.JScrollPane masterScrollPane;
private javax.swing.JTable masterTable;
private javax.swing.JButton newButton;
private javax.swing.JTextField nomeField;
private javax.swing.JLabel nomeLabel;
private javax.persistence.Query query;
private javax.swing.JButton refreshButton;
private javax.swing.JButton saveButton;
private org.jdesktop.beansbinding.BindingGroup bindingGroup;
// End of variables declaration
public static void main(String[] args) {

    /* Create and display the form */
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            JFrame frame = new JFrame();
            frame.setContentPane(new JCadMedico());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.pack();
            frame.setVisible(true);
        }
    });
}

}

Isso não é um problema, é um comportamento normal e não é relacionado ao JPA, é relacionado ao banco de dados mesmo, independente de qual.
Sempre que você insere um registro e exclui, aquele id não estará mais disponível.

Opções: Se for MySQL ou SQL Server, faça drop das tabelas e recrie-as.
Se for Oracle ou PG, basta zerar as sequences.

Entendi, então o único jeito de zerar os IDs é excluindo as tabelas… Obrigado!

Geralmente a gente coloca o id como auto_increment, por isso quem faz o controle é o banca, independente de gerarmos valor para o id. se não me engano no JPA fica @GeneratedID. A sua pratica querendo utilizar de um valor do ID que já foi excluído não é comum, pois o ID é mais para controle da tabela, para saber que são registros diferentes e nunca vejo o usuário podendo escolher o número do ID de nenhuma tabela, mas caso você queria utilizar mesmo os números já excluidos, você vai ter que alterar o @GenaratedID e nessa primeira vez dar o drop da tabela e depois o create de novo, e fazer o teste, lembrando que se tentar usar o mesmo id que já existe ele vai apenas alterar os valores e não adicionar um novo registro.

AUTO_INCREMENT é específico do MySQL. O SQL Server, que também segue o conceito de incremento, trabalha de uma maneira diferente. O Oracle e o Postgres trabalham com sequences, por exemplo.

Eu acho que uma boa pratica que ao invés de realmente excluir, você apenas muda o valor de um atributo booleano.

Ex:
update tabela set ativo = false.

Em muitos casos não é interessante perder totalmente a informação, reflita :slight_smile:

1 curtida

Dessa forma realmente é boa,principalmente se um usuário excluir uma informação que não queria e tiver que recuperar depois, o bom que o boolean consome apenas 1 bit a mais por elemento, mesmo em uma tabela grande não fará tanta diferença.

Então isso de “querer reutilizar” campos já excluidos do Banco de Dados não é uma boa prática? Achei que eu estava otimizando mas pelo jeito estava era estragando hahaha
Obrigado! Vou deixar apenas uma exceção que quando o usuário excluir todos os registros o ID zere, faço bem?

Cara, pense no seguinte, atualmente não se usa mais excluir dados. Afinal, informação é $$$.
Você, no máximo, seta uma data de exclusão e só pesquisa pelo que está sem essa informação definida.

Não precisa voltar ao 0 mesmo se excluir todos, pode começar do último sem problemas, a pessoa saber depois o ID resultante só facilita em um método futuro de busca, mas ela sempre terá opção de pesquisar por nome, cpf, etc. Além do que em um programa que não seja com o intuito de aprendizagem é muito difícil alguém excluir literalmente todos os registros, sempre fica no mínimo 1 no meio. Em muitas aplicações nem é mostrado o id para a pessoa, pois como falei antes o programa pode fazer pesquisa por outros métodos, que garante mais eficiência. As pessoas geralmente só lembram do ID do mais utilizado, mesmo se for ela mesmo que tenha atribuído um valor para ele.