简体   繁体   中英

Play Framework 2.X Models definition in a concurrent application

Developing a Play Framework 2.3.X application here using the Ebean ORM .

I just have some doubts that i really want to clarify about best practice when defining my models in order to make them "safe" in a concurrent environment.

All my models as suggested by the documentation are extending the play.db.ebean.Model and i have some instances that can be modified by different sources.

For example i have this simple model, a User

public class User extends Model {
@Id
public Long id;
public String name;
public String surname;
public String email;
public String password;
public int credits
}

that has some credits on his account. He can recharge them and can start and have jobs in background that can consume them. I red that when having concurrent access/writes to a model is a wise choice to add a

@Version
public Long version

field to each instance in order to avoid inconsistent states in the model, and when this happens an OptimisticLockException will be thrown.

The question is, is the @Version annotation the best solution in a application like mine?

Are out there some best practice that i'm missing and that could be used in order to reduce the chance of getting an optimisticLockExceptions and if yes, which ones ??

Let's say the optimisticLockExceptions occurs when making an automatic payments by the system, for example after a credit cards payment, is it safe to loop while the transaction does complete successfully, thus by not throwing an optimisticLockExceptions ?

Should i add the @Version annotation to each model of my application ?

Sorry for being so meticulous but the models layer has to be as much robust as possibile. Hoping some of you can help me, answering even to some of my questions

Greetings

Optimistic locking works like:

UPDATE TABLE_NAME SET fields = :new_fields, version = :old_version + 1 WHERE version = :old_version AND id = :id;

if nothing updated it means that object changed or deleted since last read, so you need to repeat last transaction.

Optimistic locking is good when you have a lot of reading operations from database and small count of concurrent writing operations. But when you have high concurrent writes on the same entity you will receive a lot of optimisticLockExceptions -> you will perform a lot of transaction rollbacks. For example 10 concurrent write operation on the same entity can create up to 45 failed transactions and only 10 successed. Of course in case when you repeat transaction until success. Its potencial vulnerability: some 'hacker' can perform a lot of requests that perform concurrent updates on the same entity. So I suggest to limit repeats to reasonable count.

You need to add @Version to all entities that need support of optimistic locking. Of course in case when some entity type will be updated only with another entity that already contains @Version you can don't add it, but it can produce errors in future when this behaviour changed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM