4
respostas

[Resolvido][Spring MVC] [Spring DATA JPA] [Map Chave Composta] Detached entity ao persistir

Fala pessoal,

Estou enfrentando o seguinte problema: Tenha a Entidade Venda que tem vários itens (Produtos, parcelas, serviços, nfe's).. Quando eu salvo, tudo beleza, porém na edição recebo o erro de DETACHED ENTITY PASSED TO PERSIST... em testes identifiquei que o problema está nas minhas PARCELAS que tem chave composta (VENDA + CODIGO)...

Alguma sugestão doque pode ser ?

Entidade Venda:

@Entity
@Table(name = "tb_venda")
public class Venda implements Serializable{

    @Id
    @SequenceGenerator(name="tb_venda_gen", sequenceName="tb_venda_id_venda_seq",allocationSize=1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator="tb_venda_gen")
    @Column(name = "id_venda")
    private Long codigo;

    @NotNull(message = "Tipo de venda é obrigatório")
    @Enumerated(EnumType.STRING)
    @Column(name = "tipo_venda")
    private TipoVenda tipoVenda = TipoVenda.VENDA;

    @Column(name = "data_criacao")
    private LocalDateTime dataCriacao;

    @Column(name = "valor_frete")
    private BigDecimal valorFrete = BigDecimal.ZERO;

    @Column(name = "valor_desconto")
    private BigDecimal valorDesconto = BigDecimal.ZERO;

    @ManyToOne
    @JoinColumn(name = "id_pessoa")
    private Pessoa pessoa;

    @ManyToOne
    @JoinColumn(name = "id_usuario")
    private Usuario usuario;

    @ManyToOne
    @JoinColumn(name = "id_agenda")
    private Agenda agenda;

    @Enumerated(EnumType.STRING)
    private StatusVenda status = StatusVenda.ORCAMENTO;

    @OneToMany(mappedBy = "venda", cascade = CascadeType.ALL, orphanRemoval = true)
    @ElementCollection(fetch = FetchType.LAZY)
    @MapKeyColumn(name = "id_produto")
    private Map<Long, ItemVenda> itens = new HashMap<>();

    @OneToMany(mappedBy = "venda", cascade = CascadeType.ALL)
    @ElementCollection(fetch = FetchType.LAZY)
    @MapKeyColumn(name = "id_parcela")
    private Map<Integer, Parcela> parcelas = new HashMap<>();

    @OneToMany(mappedBy = "venda", cascade = CascadeType.ALL, orphanRemoval = true)
    @ElementCollection(fetch = FetchType.LAZY)
    @MapKeyColumn(name = "id_tipo_atendimento")
    private Map<Integer, ItemAtendimento> itensAtendimento = new HashMap<>();

    @JsonIgnore
    @OneToMany(mappedBy = "venda", cascade = CascadeType.ALL, orphanRemoval = true)
    @ElementCollection(fetch = FetchType.LAZY)
    @MapKeyColumn(name = "id_nfe")
    private  Map<Long, NFeInfo> nfeInfos = new HashMap<>();

    @Transient
    private String uuid;

//GETERS & SETERS
}

Entidade Parcela:

@Entity
@Table(name = "tb_parcela_venda")
@IdClass(Parcela.ParcelaId.class)
public class Parcela implements Serializable {

    @Id
    @ManyToOne
    @JoinColumn(name = "id_venda")
    private Venda venda;

    @Id
    @Column(name = "id_parcela")
    private Integer codigo;

    @Column(name = "data_vencimento")
    private LocalDate dataVencimento;

    @Column(name="data_pagamento")
    private LocalDate dataPagamento;

    private BigDecimal valor;

    @Column(name="valor_pago")
    private BigDecimal valorPago = BigDecimal.ZERO;

    @NotNull(message = "Moeda de pagamento é obrigatório")
    @ManyToOne
    @JoinColumn(name="id_moeda")
    private MoedaPagamento moedaPagamento;

    @ManyToOne
    @JoinColumn(name = "id_usuario_ultima_modificacao")
    private Usuario usuarioUltimaModificacao;

    @Column(name = "data_ultima_modificacao")
    private LocalDateTime dataUltimaModificacao;

            // GETERS / SETERS / EQUAL  HASHCODE

    public static class ParcelaId implements Serializable {
        private Long venda;
        private Integer codigo;

        // GETERS / SETERS / EQUAL  HASHCODE

    }

}

Vlww

4 respostas

Fala Elivelton, tudo bem ?

Quando você carrega a venda pra editar possivelmente não ta trazendo as informações das parcelas (talvez em função do lazy load). Talvez se você planejar a query fazendo o join e garantindo o carregamento das informações deixe de dar problema.

Abraço!

Opaa , tudo bem.

Então no meu select ele traz tudo certinho, volta pra tela blzinha, só na hr de salvar da o problema.. To desconfiado que minha chave da PARCELA é composta, não sei se é isso que ta dando o problema.

Buscar da venda para edição:

@Override
    public Venda buscarCompleta(Long codigo) {
        CriteriaBuilder cb = manager.getCriteriaBuilder();
        CriteriaQuery q = cb.createQuery(Venda.class);
        Root o = q.from(Venda.class);
        o.fetch("itens", JoinType.LEFT);
        o.fetch("parcelas", JoinType.LEFT);
        o.fetch("itensAtendimento", JoinType.LEFT);
        o.fetch("nfeInfos", JoinType.LEFT);
        q.select(o);
        q.where(cb.equal(o.get("codigo"), codigo));

        Venda order = (Venda)manager.createQuery(q).getSingleResult();
        return order;
    }

Hm, que estranho! Da uma olhada como a tabela foi gerada na base. Não entendi muito bem qual pode ser o problema.

Você precisa realmente trabalhar com um mapa para as parcelas ?

Opa, desculpa a demora. rsrs.. Só agr consegui voltar para responder.

A Map é devido eu várias listas dentro do mesmo objeto Venda(itens, atendimentos, nfes, parcelas ....) Com List estava me retondo erro de 'multiple bags'... Ai resolvi implementando com Maps somente.

Agora o problema que eu estava passando com a perguntando foi RESOLVIDO :D

Somente passei de usar @IdClass para @EmbeddedId.

Funcionou blzinha. o meu Map na Venda continuou da mesma forma.

Vlwww Pelo suporte !!