Optimistic Lock; Why not throw an exception?

4

I tried to simulate an optimistic Lock situation where you try to update the same record twice, but the exception is not triggered.

I think it's interesting that even after changing the value of the holder and giving a MERGE, the version value is not updated in the object or in the base record.

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("financas");
    EntityManager em1 = emf.createEntityManager();
    EntityManager em2 = emf.createEntityManager();

    em1.getTransaction().begin();
    em2.getTransaction().begin();

    Conta c1 = em1.find(Conta.class,1);
    em1.lock(c1, LockModeType.OPTIMISTIC);
    em1.merge(c1);
    em1.getTransaction().commit();
    Conta c2 = em2.find(Conta.class,1);
    em2.lock(c2, LockModeType.OPTIMISTIC);
    em2.merge(c2);
    em2.getTransaction().commit();

------------- UPDATED ---------------------

Account Class Content:

package br.com.financas.modelo;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Version;

@Entity
public class Conta {

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    private String titular;
    private String banco;
    private String agencia;
    private String numero;

    @Version
    private int versao;

    public int getVersao() {
        return versao;
    }
    public void setVersao(int versao) {
        this.versao = versao;
    }
    @OneToMany(mappedBy="conta")
    private List<Movimentacao> movimentacoes;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTitular() {
        return titular;
    }
    public void setTitular(String titular) {
        this.titular = titular;
    }
    public String getBanco() {
        return banco;
    }
    public void setBanco(String banco) {
        this.banco = banco;
    }
    public String getAgencia() {
        return agencia;
    }
    public void setAgencia(String agencia) {
        this.agencia = agencia;
    }
    public String getNumero() {
        return numero;
    }
    public void setNumero(String numero) {
        this.numero = numero;
    }
    public List<Movimentacao> getMovimentacoes() {
        return movimentacoes;
    }
    public void setMovimentacoes(List<Movimentacao> movimentacoes) {
        this.movimentacoes = movimentacoes;
    }


}

Why the exception is not thrown?

    
asked by anonymous 28.02.2017 / 21:25

1 answer

7

The exception is not thrown for two reasons:

1) No changes were made to the entity either in the first or the second context in which it was obtained and persisted, so there is no way to conflict in the second context.

2) The transaction of the first context has been completed (committed ) before the entity was obtained in the second context. So even if there was no 1 problem, there would still be no exception because between the get and persistence of the entity in the second context no change was made in another context.

For an exception, the code needs to look something like this:

Conta c1 = em1.find(Conta.class,1);
em1.lock(c1, LockModeType.OPTIMISTIC);
c1.setNumero(novoNumero);       // linha adicionada
em1.merge(c1);
//em1.getTransaction().commit();   linha removida
Conta c2 = em2.find(Conta.class,1);
em2.lock(c2, LockModeType.OPTIMISTIC);
em1.getTransaction().commit();  // linha adicionada
c2.setNumero(aindaOutroNumero); // linha adicionada
em2.merge(c2);
em2.getTransaction().commit();

In the code above, the version column has been updated and persisted after the entity is retrieved again in another context. So when the entity is finally persisted in the other context, the value of version found in the base is different from that in the entity in memory, which will throw an exception of another user ".

    
06.03.2017 / 14:52