5
respostas

Erro ao adicionar itens a uma lista apos o insert

Em um projeto JavaFx tenho uma entity documento com uma lista de tecnicos assinantes

Documento.java

@OneToMany(mappedBy = "documento", cascade = CascadeType.ALL)
private List<TecnicoAssinante> assinantes = new ArrayList<>();

 public void adicionarTecnicoAssinante(TecnicoAssinante assinante){
 assinante.setDocumento(this);
 this.assinantes.add(assinante);
}

TecnicoAssinante.java

@ManyToOne
private Documento documento;

public void setDocumento(Documento documento) {
    this.documento = documento;
}

Ao salvar o item documento com os itens já adicionados tudo funciona perfeitamente

public void Salvar() {
    try{
        EntityManager em = JPAService.getEntityManager();
        DocumentoDaoJDBC documentoDaoJDBC = new DocumentoDaoJDBC(em);
        em.getTransaction().begin();
        for (FXMLLoader fxml : Application.getFxmlLoaders()){
            if (fxml.getController() instanceof Salvar){
                ((Salvar) fxml.getController()).salvar();
            }
        }
        if (Application.getDocumento().getId() == null){
            documentoDaoJDBC.insert(Application.getDocumento());
        }else {
            documentoDaoJDBC.update(Application.getDocumento());
        }
        em.getTransaction().commit();
        em.close();
    } catch (Exception e) {
        Alerts.showAlert("Falha", "Falha ao salvar dados", e.getMessage(), Alert.AlertType.ERROR);
    }finally {
        Alerts.showAlert(null, null, Application.getDocumento().getAssinantes().toString(), Alert.AlertType.INFORMATION);
        reload();
    }
}

@Override
public void insert(Documento documento) {
    try{
        em.persist(documento);
        Alerts.showAlert("Sucesso", Application.getNovaTela().getTitulo() + " incluído com sucesso", null, Alert.AlertType.INFORMATION);
    }catch (Exception e){
        Alerts.showAlert("Falha ao incluir auto", "Houve uma falha na inclusão do auto/termo\nSe o problema persistir contate o suporte técnico", e.getMessage(), Alert.AlertType.WARNING);
    }finally {
        em.close();
    }
}


@Override
public void update(Documento documento) {
    try{
        em.merge(documento);
        Alerts.showAlert("Sucesso", "Auto/termo foi atualizado com sucesso!", null, Alert.AlertType.INFORMATION);
    } catch (EntityNotFoundException e) {
        Alerts.showAlert("Não encontrado", "Auto/termo não encontrado", e.getMessage(), Alert.AlertType.WARNING);
    } catch (Exception e) {
        Alerts.showAlert("Falha ao deletar", "Houve uma falha ao atualizar auto/termo\nSe o problema persistir contate o suporte técnico", e.getMessage(), Alert.AlertType.WARNING);
    }finally {

    }
}

Porem, ao adicionar outros técnicos em um documento previamente salvo os novos técnicos assinantes não recebem id passando a duplicar os itens no banco a cada novo "update" de documento.

Como solucionar esse problema?

5 respostas

Olá!

O seu método de insert finaliza o EntityManager antes do commit acontecer fora do DAO.

Em termos de responsabilidade, essa parte de abrir e fechar transações, lidar com EntityManager e outras questões relacionadas a persistência poderiam ficar no DAO, ou todas para fora dele, pois do jeito que está, essa responsabilidade fica dividida entre as duas classes e pode causar essas confusões.

@Override
public void insert(Documento documento) {
    try{
        em.persist(documento);
        Alerts.showAlert("Sucesso", Application.getNovaTela().getTitulo() + " incluído com sucesso", null, Alert.AlertType.INFORMATION);
    }catch (Exception e){
        Alerts.showAlert("Falha ao incluir auto", "Houve uma falha na inclusão do auto/termo\nSe o problema persistir contate o suporte técnico", e.getMessage(), Alert.AlertType.WARNING);
    }finally {
        em.close(); // tenta remover 
    }
}

Sim, concordo, mas mesmo removendo o erro permanece...

Hmm... Manda o código das duas classes, por favor.

E o que este Controller faz?

for (FXMLLoader fxml : Application.getFxmlLoaders()){
            if (fxml.getController() instanceof Salvar){
                ((Salvar) fxml.getController()).salvar();
            }
        }

Bom dia, errei no conceito de merge do hibernate, revendo o conteúdo do curso https://cursos.alura.com.br/course/persistencia-jpa-introducao-hibernate consegui solucionar o problema refatorando o código do método update:

@Override
public void update(Documento documento) {
    try{
        Application.setDocumento(em.merge(documento));
        Alerts.showAlert("Sucesso", "Auto/termo foi atualizado com sucesso!", null, Alert.AlertType.INFORMATION);
    } catch (EntityNotFoundException e) {
        Alerts.showAlert("Não encontrado", "Auto/termo não encontrado", e.getMessage(), Alert.AlertType.WARNING);
    } catch (Exception e) {
        Alerts.showAlert("Falha ao deletar", "Houve uma falha ao atualizar auto/termo\nSe o problema persistir contate o suporte técnico", e.getMessage(), Alert.AlertType.WARNING);
    }finally {

    }
}

Respondendo a sua pergunta, o projeto é em javaFx, encontrei duas abordagens para lidar com a navegação entre telas, escolhi utilizar um único palco e vou alterando o cenário, cada cenário é composto por mais de um fxml, cada fxml possui um controller para executar métodos pertinentes ao mesmo, no caso o existe uma interface Salvar responsável por transferir os dados dos TextFields/TextAreas para a Application.Documento, assim, realiza um foreach em cada fxml da tela, capitura seus controlers, atualiza o Application.Documento e depois executa o insert/update conforme o caso.

Muito obrigado pela ajuda.

Refatorando para evitar o acoplamento:

@Override
public Documento update(Documento documento) {
    try{
        Alerts.showAlert("Sucesso", "Auto/termo foi atualizado com sucesso!", null, Alert.AlertType.INFORMATION);
        return em.merge(documento);
    } catch (EntityNotFoundException e) {
        Alerts.showAlert("Não encontrado", "Auto/termo não encontrado", e.getMessage(), Alert.AlertType.WARNING);
        return documento;
    } catch (Exception e) {
        Alerts.showAlert("Falha ao deletar", "Houve uma falha ao atualizar auto/termo\nSe o problema persistir contate o suporte técnico", e.getMessage(), Alert.AlertType.WARNING);
        return documento;
    }finally {
    }
}