Problem saving two sales at the same time - JAVA

Asked

Viewed 74 times

0

I have a problem saving two sales at the same time on different computers, when it finishes both, one replaces the other. I am 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

Method List All:

public List<T> listarTodos() {
    String consulta = "FROM " + entityClass.getSimpleName() + " order by id desc";
    Query query = getEntityManager().createQuery(consulta);
    return query.setMaxResults(20).getResultList();
}
  • How is your entity Venda? You can edit the question and put her code here?

  • And if possible that of VendaFacade and of ItemVendaFacade also. At least the methods listarTodos().

  • I already have my answer half-written, but I need to know what’s in the VendaFacade.salvar(Venda) to finish her.

1 answer

1

In its entity Venda, you already have it:

@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 trusting that the column is AUTO_INCREMENT in the database. Therefore, you basically say that the database is responsible for creating the ids automatically.

Yet you do it:

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

And that:

                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 going over the GenerationType.IDENTITY of Iberian and the AUTO_INCREMENT database. The best way to ensure that the generated id is unique is to rely on AUTO_INCREMENT. By using this Setter, you give up the AUTO_INCREMENT And it basically ends up asking for competition problems if two threads are running this method at the same time, as they will generate ids that will collide. Also, the performance is bad because you will make Hibernate read all the records (or at least 20 of them) with the use of listarTodos().

You better trust the GenerationType.IDENTITY and in the AUTO_INCREMENT. The id will be populated when you save the entity in the database with a merge or persist.

And your method salvar1() gets 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";
    }
}

The Hibernate will already set all ids from the AUTO_INCREMENT for all entities Venda and ItemVenda. I even recommend excluding the methods setId (but leave the 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 that’s beyond the scope of this question.

  • Dude I did it just for testing public String salvarTeste() { Synchronized (sell) { vendaFacade.salvarNota(sell); Return "/budget/list? faces-redirect=true"; } } .

  • @Leandrosantos How and where this field venda is declared? JPA entities should never be shared between different threads, and the fact that you are using synchronized hints that’s exactly what you’re doing.

  • I put Synchronized now to see if it solves rs, more unsuccessfully. public string salvarTeste() { Synchronized (this) { vendFacade.salvarNota(venda); Return "/orcamento/list? faces-redirect=true"; } } On my new button() I just instate a new object.

  • @Leandrosantos I think to understand in detail the root of the problem, you will need to put more parts of your code in the question.

  • I think I’ve reached the maximum of characters, but I can play in a dontPad can be

  • @Leandrosantos Yes, it can be.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.