OptimisticLockException with Ebean/Play

latj picture latj · Dec 2, 2013 · Viewed 7.6k times · Source

I have a Play 2.1.3 Java app using Ebean. I am getting the OptimisticLockException below.

[OptimisticLockException: Data has changed. updated [0] rows sql[update person 
set name=? where id=? and email=? and name=? and password is null and created=? 
and deleted is null] bind[null]]

I understand that it is trying to tell me the record has changed between when I read it and when I tried to write it. But the only change is happening in this method.

public void updateFromForm(Map<String, String[]> form) throws Exception {
    this.name = form.get("name")[0];

    String password = form.get("password")[0];
    if (password != null && password.length() != 0) {
        String hash = Password.getSaltedHash(password);
        this.password = hash;
    }

    this.update();
}

Am I doing this wrong? I saw similar logic in zentasks. Also, should I be able to see the the values for the bind variables?

UPDATE: I am calling updateFromForm() from inside a controller:

@RequiresAuthentication(clientName = "FormClient")
public static Result updateProfile() throws Exception {

    final CommonProfile profile = getUserProfile();
    String email = getEmail(profile);           
    Person p = Person.find.where().eq("email", email).findList().get(0);

    Map<String, String[]> form = request().body().asFormUrlEncoded();

    if (p == null) {
        Person.createFromForm(form);
    } else {
        p.updateFromForm(form);
    }

    return ok("HI");
}

Answer

Sindri Traustason picture Sindri Traustason · Nov 28, 2014

I have an alternative approach to this, where I add the annotation

@EntityConcurrencyMode(ConcurrencyMode.NONE)

to the Entity class.

This disables the optimistic locking concurrent modification check meaning the SQL becomes

update person set name=? where id=?

This is even more optimistic since it simply overwrites any intermediate changes.