OptimisticLockException with Ebean and Play Framework 2

妖精的绣舞 提交于 2019-12-09 12:24:46

问题


I am using Ebean with Play Framework 2 and sometimes it falls with OptimisticLockException of such kind:

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]]]

This happen when few actors start to access database.

So, Manager class is:

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() and update() hooks used instead @PrePersist annotations, because of Ebean doesn't support it. As I know @Version annotation allways brings Optimistic lock mode, so I start to use such trick. I know what Optimistick lock is, but how this situation should be solved, when many actors should modify same db record, where last modification wins?


回答1:


Solution:

The problem: Saving a detached EBean model directly from the Play Form causes either OptimisticLockException, or when using @Version it causes NullpointerException.

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

The solution: The form should support supplying it an object from database, before binding from the request parameters. The parameters found in the request should then overwrite the relevant properties on the object. Perhaps call fill() before bindFromRequest():

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



回答2:


I resolved this OptmistLockException issue just passing the entity id to the controller when trying to update. To prevent user from changing values, the value was passed as a hidden field.

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

On the controller side, I check if the received form has errors. In negative case, I update the attached entity in the form.

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


来源:https://stackoverflow.com/questions/12617676/optimisticlockexception-with-ebean-and-play-framework-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!