I have a server function which is called by many clients, many times exactly at the same time. The server function does the following:
This goes wrong when two or more clients run the function at the same time, multiple x objects get added to the database.
I simply solved this by creating a singleton manager class with a synchronized method which does the above.
Works nicely, cause now the function can only be called by one client at a time. (but i do get a problem when there are 2 servers, but that isn't the case yet)
But i was wondering is there a better way to solve this problem with jpa?
Yes, this whole operation should be executed inside a transaction, such as provided by JTA or Spring's @Transactional
. If the transaction is isolated at the proper level (I think REPEATABLE_READ
for this case), the underlying persistence system will ensure that colliding writes don't occur, either by blocking one transaction until the other is complete (essentially what synchronized
does in Java), or by stopping and rolling back the second transaction when it detects the conflict (which you can then retry).
The only foolproof solution I can think of is create database level Constraints. This is because
synchronized
will impact on application performance as users have to wait in line while the action is being performed by other users, which I am pretty sure will not be acceptable situation in any case.What you need is create constraints on column values for simple data validation for example not null
or unique
etc. and for complex situation what I have done is create a trigger on database table which checks the value which are being inserted or updated and if it violates the condition it will SIGNAL
SQLSTATE
and even set a message which will provide reason for failure and you can handle these exception in your Java code for appropriate message to user. For this you will need to have little knowledge of PL/SQL
and if you don't its not that difficult to learn and implement it. Have a look at this question here with some what similar context.
Now there are certain situation where you can not directly create database level constraints if the database you use does not support e.g. almost all NoSQL
databases, if database is MySQL
and engine for table is MyISAM
etc. in those situations all you can do is use certain write
commit
locking by some common application code between multiple instances of application. I have not myself tried to figure out proper solution in these situation as this will rarely occur.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With