Urbanleg
Urbanleg

Reputation: 6532

Hibernate \ JPA usage on a high concurrency web application

So we are developing a high concurrency web application that is pretty much a big multiplayer game.

Our server is using spring MVC , spring data , MySQL and JPA.

We are now discussion the methodology we should use in regard to concurrency.

One of the suggestions that came up pretty much got me out of my comfort zone:

I'm used to use the good old fashioned orm style:

 @Transactional
 @public void doSomeMagic() {
    User user = userDao.findById(id);
    user.setStuff(stuff);
    ...       
 }

now, the suggestion that came up said the following:

since the above methodology is prone to concurrency mishaps (and probably mitigated by locking mechanism), why don't we use SQL \ JPQL updates instead? why even bothering fetching the user if our only goal is to update its fields?

we could do something like this:

 userDao.updatePlayer(stuffParameters);   // "update Player p set stuffParameters...."

Now , i have some question about this methodology:

1) How common is the practice of using update queries instead of updating through the ORM alone?

2) What exactly are the pitfalls of this methodology?

3) Are there any hybrid solutions? or another alternative that i haven't spoke of?

4) Can anyone that actually used this methodology tell some of the rules \ realizations he got ?

Thanks!

Upvotes: 3

Views: 857

Answers (2)

Angular University
Angular University

Reputation: 43087

Hibernate supports batch updates via HQL/JPSQL, see here an example:

String jpqlUpdate =
        "update Customer c " +
        "set c.name = :newName " +
        "where c.name = :oldName";
int updatedEntities = entityManager.createQuery( jpqlUpdate )
        .setString( "newName", newName )
        .setString( "oldName", oldName )
        .executeUpdate();

This is usual in the case of batch processing, when you need to issue a modification query that changes a lot of entities in the database, but don't want to incur the overhead of loading all entities in-memory, dirty checking them and flushing changes to the database.

The pitfall is that batch queries can modify objects in the database that are already in the session, and in that case the data in the session will be stale.

It is possible to have the update incrementing the version by using the keyword versioned in front of update.

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691755

First of all, I'd like to mention that your good old fashioned orm style shouldn't use save() at all. Attached entities are automatically persistent. The save() call is useless. Every change made to an attached entity will be persisted at commit time (or sooner).

I'd also like to point that there are no more concurrency problems with this approach than there are with an approach consisting in using update queries. To the contrary: if optimistic locking (using @Version) is used, the old fashioned way of doing has less concurrency problems than the update query approach (which simply updates the state regardless of whether some concurrent transaction also has updated it).

Regarding your different points:

  1. Not very common, because this is much more cumbersome than just modifying the entities and let JPA handle the update queries. It's also much more complex to handle complex use cases, and makes to code look like JDBC code, which JPA allows avoiding in the first place.

  2. The pitfalls are that optimistic locking is bypassed if you use update queries, as is the first-level cache. So if you have loaded an entity and use an update query to update its state, the loaded entity will still hold the old state.

  3. You can use both approaches together. Just beware of the pitfalls I mentioned at point 2.

  4. Update queries can make sense, especially if the goal is to update many entities at once. I would only downgrade to such an approach if you have proven that you had a performance problem, and that this performance problem could be solved by using this approach. Otherwise, it's just premature optimization, which has a high productivity and robustness cost.

Upvotes: 6

Related Questions