Playframework 2.0 Ebean和Play框架2的OptimisticLockException

Playframework 2.0 Ebean和Play框架2的OptimisticLockException,playframework-2.0,ebean,Playframework 2.0,Ebean,我将Ebean与Play Framework 2一起使用,有时它会与OptimisticLock一起使用,但此类情况除外: 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

我将Ebean与Play Framework 2一起使用,有时它会与OptimisticLock一起使用,但此类情况除外:

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

}
使用save()和update()钩子代替@PrePersist注释,因为Ebean不支持它。 我知道@Version注释总是带来乐观锁定模式,所以我开始使用这种技巧。我知道Optimistick lock是什么,但当许多参与者修改同一个db记录时,这种情况应该如何解决,最后一次修改的结果是什么?

问题:直接从播放表单保存分离的EBean模型会导致OptimisticLockException,或者在使用@Version时会导致NullpointerException

Form<Venue> form = form(Venue.class).bindFromRequest();
form.get().update(id); // this causes the exception
Form Form=Form(场馆.class).bindFromRequest();
form.get().update(id);//这导致了异常
解决方案:表单应该支持在从请求参数绑定之前,从数据库向其提供一个对象。然后,请求中找到的参数应覆盖对象上的相关属性。可能在bindFromRequest()之前调用fill():

Form Form=Form(场馆.class).fill(场馆.find.byId(id)).bindFromRequest();
form.get().update(id);

我解决了这个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();
     }
 }
公共静态结果更新(){
Form filledForm=Form.bindFromRequest();
if(filledForm.hasErrors()){
闪光器(“app.oh_snap”,“app.change_things”);
}否则{
实体=filledForm.get();
entity.update();
}
}

是的,你说得对。但我的麻烦不在这里。问题出在类层次结构深层的@Version注释中。不管怎么说,你的回答对于第一次面对这样麻烦的人来说是非常有用的。让它被接受。在表单绑定之前,您如何获得调用vention.find.byId(id))的id?任何聪明的用户都可以查看,最重要的是,可以从UI更改隐藏字段的值。这不是一个好的解决方案。
 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();
     }
 }