Problem saving two sales at the same time - JAVA

0

I have a problem saving two sales at the same time on different computers, when both ends, one replaces the other. I'm using @ManagedBean , @SessionScoped .

This is my method salvar() in the controller:

public String salvar1() {

    if (venda.getItensVenda().isEmpty()) {

        FacesContext.getCurrentInstance().
                addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_FATAL,
                                "Não é possível gerar um orçamento sem adicionar produtos!", ""));
        return "/list?faces-redirect=true";
    } else {

        try {

            if (venda.getId() == null) {
                Long id1 = vendaFacade.listarTodos().get(0).getId();
                venda.setId(id1 + 1);
            }

            System.out.println("Aqui Entrou");
            for (int i = 0; i < venda.getItensVenda().size(); i++) {
                if (venda.getItensVenda().get(i).getId() == null) {
                    Long id3 = itemVendaFacade.listarTodos().get(0).getId();
                    Long n = (long) id3 + i + 1;
                    System.out.println("Aqui Conta");
                    venda.getItensVenda().get(i).setId(n);
                    venda.getItensVenda().get(i).setNome(venda.getItensVenda().get(i).getPlantio().getNome());

                }
            }
            if (venda.getPessoa() instanceof PessoaFisica) {
                venda.setVenda(Boolean.FALSE);
                venda.setValida("PF");
                venda.setNomeFun(venda.getFuncionario().getNome());

                vendaFacade.salvar(venda);
            } else {
                venda.setValida("PJ");
                venda.setNomeFun(venda.getFuncionario().getNome());
                venda.setVenda(Boolean.FALSE);

                vendaFacade.salvar(venda);
            }


            return "/orcamento/list?faces-redirect=true";

        } catch (Exception e) {
            FacesContext.getCurrentInstance().
                    addMessage(null,
                            new FacesMessage(FacesMessage.SEVERITY_FATAL,
                                    "Ocorreu um erro no parcelamento, verifique!", ""));
            return "form?faces-redirect=true";
        }

    }
}

No Facade:

 entity = em.merge(entity);

Entity:

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

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column
    private Long id;
    @Column
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dtVenda = new Date();
    @Temporal(javax.persistence.TemporalType.TIMESTAMP)
    private Date dtVendaTela = new Date();
    @Column
    private String nomeFun;
    @Column
    private String cpfNota;
    @Column
    private String tipoDeVenda;
    @Column
    private String cnpjNota;
    @Column
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dataVencimento = new Date();
    @Column
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date dataAtualizacao = new Date();
    @Column
    private BigDecimal total = BigDecimal.ZERO;
    @Column
    private BigDecimal totalFiscal = BigDecimal.ZERO;
    @Column
    private Boolean fiscal;
    @Column
    private Boolean recebido = Boolean.FALSE;
    @Column
    private Boolean troca = Boolean.FALSE;
    @Column
    private BigDecimal entrada = BigDecimal.ZERO;
    @Column
    private BigDecimal totalDesc = BigDecimal.ZERO;
    @Column
    private BigDecimal totalDescFiscal = BigDecimal.ZERO;
    @Column
    private BigDecimal totalDescEn = BigDecimal.ZERO;
    @Column
    private BigDecimal totalDescEnFiscal = BigDecimal.ZERO;
    @Column
    private BigDecimal acrescimo = BigDecimal.ZERO;
    @Column
    private BigDecimal desconto = BigDecimal.ZERO;
    @Column
    private BigDecimal valorDesconto = BigDecimal.ZERO;
    @Column
    private Boolean venda = Boolean.FALSE;
    @Column
    private String valida;
    @Column(columnDefinition = "TEXT")
    private String xml;
    private Boolean naoTransmitida;
    @ManyToOne
    private Bandeira bandeira;
    @Column
    private String numeroDoc;
    @Column
    @Min(value = 1)
    private Integer qtdParcela = 1;
    @Column
    private String tipoPagamento = "A VISTA";
    @Column(length = 600)
    private String obs = "".toUpperCase();
    private String tipoDoc;
    private String agenciaC;
    private String modalidadefrete;
    private Integer intervalo = 30;
    @Column
    private Boolean vendaFiscal = Boolean.FALSE;
    @Column
    private BigDecimal creditoHaver = BigDecimal.ZERO;
    @Column(precision = 8)
    private BigDecimal quantidadeItens = BigDecimal.ZERO;
    @ManyToOne
    @JoinColumn
    private Pessoa pessoa;
    @ManyToOne
    @JoinColumn
    private Funcionario funcionario;
    @ManyToOne
    @JoinColumn
    private Banco banco;
    private String modeloNota;
    @ManyToOne
    private PlanoContas planoContas;
    @Column
    private BigDecimal valorCheque = BigDecimal.ZERO;
    private String veiculo;
    private String especie = "1";
    private String marca = "1";
    private String numeracao = "1";
    private String pesob;
    private String pesol;
    private String quantidade = "1";
    private String rntc;
    @OneToMany(cascade = CascadeType.ALL,
            fetch = FetchType.LAZY, orphanRemoval = true,
            mappedBy = "venda")
    private List<ItemVenda> itensVenda = new ArrayList<>();
    @OneToMany(cascade = CascadeType.ALL,
            fetch = FetchType.LAZY,
            mappedBy = "venda")
    private List<Parcela> parcelas;
    @ManyToOne
    @JoinColumn
    private Empresa empresa;
    @Column
    private Boolean entregue = Boolean.FALSE;
    private Date dataVencimentoCheque;
    private String titular;
    @Column
    private Boolean vFiscal;
    @Column
    private String dtOriginal;
// gets e sets

List All Method:

public List<T> listarTodos() {
    String consulta = "FROM " + entityClass.getSimpleName() + " order by id desc";
    Query query = getEntityManager().createQuery(consulta);
    return query.setMaxResults(20).getResultList();
}
    
asked by anonymous 20.07.2018 / 16:37

1 answer

1

In your entity Venda , you already have this:

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Long id;

That is, you already tell Hibernate to create the entity id. It will do this by relying on the fact that the column is AUTO_INCREMENT in the database. So, you basically say that the database is responsible for creating the ids automatically.

However, you do this:

            Long id1 = vendaFacade.listarTodos().get(0).getId();
            venda.setId(id1 + 1);

And this:

                Long id3 = itemVendaFacade.listarTodos().get(0).getId();
                Long n = (long) id3 + i + 1;
                System.out.println("Aqui Conta");
                venda.getItensVenda().get(i).setId(n);

That is, in these places you are setting the id yourself and passing over GenerationType.IDENTITY of hibernate and AUTO_INCREMENT of the database. The best way to ensure that the generated id is unique is to trust AUTO_INCREMENT . When using this setter, you give up AUTO_INCREMENT and this ends up practically asking you to have concurrency problems if two threads are executing this method at the same time, because they will generate ids that will collide. Also, performance is poor because you are going to have hibernate read all the records (or at least 20 of them) with the listarTodos() usage.

You'd better trust GenerationType.IDENTITY and AUTO_INCREMENT . The id will populate when you save the entity to the database with merge or persist .

And your salvar1() method looks like this:

public String salvar1() {

    if (venda.getItensVenda().isEmpty()) {

        FacesContext.getCurrentInstance().
                addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_FATAL,
                                "Não é possível gerar um orçamento sem adicionar produtos!", ""));
        return "/list?faces-redirect=true";
    }

    try {
        for (int i = 0; i < venda.getItensVenda().size(); i++) {
            ItemVenda iv = venda.getItensVenda().get(i);
            if (iv.getId() == null) {
                System.out.println("Aqui Conta");
                iv.setNome(iv.getPlantio().getNome());
            }
        }
        venda.setValida(venda.getPessoa() instanceof PessoaFisica ? "PF" : "PJ");
        venda.setNomeFun(venda.getFuncionario().getNome());
        venda.setVenda(Boolean.FALSE);
        vendaFacade.salvar(venda);
        return "/orcamento/list?faces-redirect=true";

    } catch (Exception e) {
        FacesContext.getCurrentInstance().
                addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_FATAL,
                                "Ocorreu um erro no parcelamento, verifique!", ""));
        return "form?faces-redirect=true";
    }
}

Hibernate will already set all ids from AUTO_INCREMENT to all Venda and ItemVenda entities. I even recommend that you exclude the setId methods (but leave getId ) to make it clear that the id should never be set manually and that only hibernate can set them.

There are other changes that I could propose to improve encapsulation and other things, but this is beyond the scope of this question.

    
20.07.2018 / 19:28