2012-09-27 14 views
7

Sto usando Ebean con Play Framework 2 ed a volte cade con OptimisticLockException di questo tipo:OptimisticLockException con Ebean and Play Framework 2

play.core.ActionInvoker$$anonfun$receive$1$$anon$1: Execution exception [[OptimisticLockException: Data has changed. updated [0] rows sql[update manager set modification_time=?, session_id=?, expiration_date=? where id=? and rating=? and creation_time=? and modification_time=? and name=? and surname=? and login=? and password_hash=? and email=? and session_id=? and expiration_date=?] bind[null]]] 

Questo succede quando pochi attori iniziano a accedere al database.

Quindi, classe Manager è:

public class Manager extends Model { 
@Getter @Setter 
Long id; 

@Getter @Setter 
private String name; 

@Getter @Setter 
private String surname; 

@Column(unique = true) 
@Getter @Setter 
private String login; 

@Getter @Setter 
private String passwordHash; 

@Getter @Setter 
private String email; 

@Embedded 
@Getter @Setter 
private ManagerSession session; 

@Getter 
private Timestamp creationTime; 

@Getter 
private Timestamp modificationTime; 

@Override 
public void save() { 
    this.creationTime  = new Timestamp(System.currentTimeMillis()); 
    this.modificationTime = new Timestamp(System.currentTimeMillis()); 
    super.save(); 
} 

@Override 
public void update() { 
    this.modificationTime = new Timestamp(System.currentTimeMillis()); 
    super.update(); 
} 

} 

Salva ganci() e update() utilizzati annotazioni invece @PrePersist, a causa della Ebean non lo supporta. Come noto, l'annotazione della versione porta sempre la modalità di blocco ottimistico, quindi inizio a utilizzare tale trucco. So cos'è il blocco di Optimistick, ma come dovrebbe essere risolta questa situazione, quando molti attori dovrebbero modificare lo stesso record db, dove vince l'ultima modifica?

risposta

15

Solution:

Il problema: Salvare un modello di EBean staccato direttamente dal modulo di gioco fa sì che sia OptimisticLockException, o quando si utilizza @Version provoca NullPointerException.

Form<Venue> form = form(Venue.class).bindFromRequest(); 
form.get().update(id); // this causes the exception 

La soluzione: Il modulo deve sostenere fornire un oggetto dal database, prima di associare dai parametri di richiesta. I parametri trovati nella richiesta dovrebbero quindi sovrascrivere le relative proprietà sull'oggetto. Forse chiamare riempimento() prima bindFromRequest():

Form<Venue> form = form(Venue.class).fill(Venue.find.byId(id)).bindFromRequest(); 
form.get().update(id); 
+0

Sì, hai ragione. Ma il mio problema non era qui. Il problema era nell'annotazione di @Version nella gerarchia di classi. Ad ogni modo, la tua risposta è molto utile per chi deve affrontare un tale problema per la prima volta. Lascia che sia accettato. –

+0

Come si ottiene ** id ** per chiamare * Venue.find.byId (id)) * prima del bind del modulo? –

2

ho risolto questo problema OptmistLockException solo di passaggio l'entità id al controller quando si cerca di aggiornare. Per impedire all'utente di modificare i valori, il valore è stato passato come campo nascosto.

<input type="hidden" name="id" value="@formVar(<identifierVariable>).value"/> 

Sul lato controller, controllo se il modulo ricevuto presenta errori. In caso negativo, aggiorno l'entità allegata nel modulo.

public static Result update() { 
    Form<Entity> filledForm = form.bindFromRequest(); 
    if (filledForm.hasErrors()) { 
     flashError("app.oh_snap", "app.change_things"); 
    } else { 
     Entity entity = filledForm.get(); 
     entity.update(); 
    } 
} 
+0

Qualsiasi utente intelligente sarà in grado di visualizzare e, soprattutto, ** modificare ** il valore del campo nascosto dall'interfaccia utente. Questa non può essere una buona soluzione. –

Problemi correlati