2012-09-27 68 views
7

我使用Ebean有Play框架2,有時用這樣那樣的OptimisticLockException下降:OptimisticLockException與Ebean和播放框架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]]] 

這時候幾個演員開始訪問數據庫的發生。

所以,經理類是:

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(); 
} 

} 

節省代替@PrePersist註解()和update()掛鉤,因爲Ebean不支持它。 正如我所知@Version註釋allways帶來樂觀鎖定模式,所以我開始使用這種技巧。我知道Optimistick鎖是什麼,但是如何解決這種情況,當許多演員應該修改相同的數據庫記錄,最後修改獲勝?

回答

15

Solution:

問題:直接從播放表保存分離EBean模型會導致要麼OptimisticLockException,或使用@Version當它引起的NullPointerException。

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

解決方案:表單應該支持在從請求參數綁定之前向數據庫提供一個對象。然後請求中的參數應該覆蓋對象上的相關屬性。 bindFromRequest()之前或者叫填():

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

是的,你說得對。但是我的麻煩不在這裏。問題出現在類層次結構深處的@Version註釋中。 無論如何,對於第一次面對這樣的麻煩的人來說,你的答案是非常有用的。讓它被接受。 –

+0

如何在表單綁定之前獲得** id **來調用* Venue.find.byId(id))*? –

2

我解決了這個問題OptmistLockException剛好路過的實體ID控制器試圖更新的時候。爲防止用戶更改值,該值作爲隱藏字段傳遞。

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

在控制器端,我檢查收到的表格是否有錯誤。在否定的情況下,我更新表單中的附加實體。

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

任何聰明的用戶將能夠查看,最重要的是,**從UI更改隱藏字段的值。這不是一個好的解決方案。 –