I have a Postgres table named mytable which I am using from JPA/Hibernate entity to manage it.
The table has a column name mycolumn with default value set as FALSE.
Now there will be many concurrent update to that column and I want only to update if and only if value is FALSE, and once it is updated to TRUE by any of one, no other concurrent requests must be able to update it, never ever, resulting in something like 'Value has been already updated and you can not update it.'
AFAIK Locking is not going to help with this.
How to handle this with JPA/Hibernate in concurrent situation?
Thanks
Edit: revise title
Related
I am trying to have a table with an "order" column to allow rearranging the order of data. Is this possible using jpa? Maybe something similar to #OrderColumn but on the table itself.
Basically I want to add a new column called "order" that saves the order the records. If a record is added, it would automatically get a "order" value. If a record was deleted, the "order" of the remaining would be automatically updated. Additionally if possible, to rearrange the orders by moving one record to an lower "order" and it would push the others
There is no way to do this out of the box, but you can implement this yourself if you want. Just query for the count of objects right before persisting and set the count + 1 as value for that order column. Make sure that the order column is declared as being unique i.e. with a unique constraint.
Note that your requirement is pretty exotic and will likely require some kind of table lock or retry mechanism if you have high concurrency.
IMO you should ask whoever gave you this requirement what the goal is that should be achieved. I bet that you will find out you don't need this after all.
I have a database with table "Customers". I am currently creating a customer application where administrators should be able to create/delete etc customers. so I want to have one safty in case you delete a customers by mistake. My question are, what is the best way to restore a customer if being deleted?
I was thinking of just having an own table for deleted customers but dont know if there are other ways to achive this.
One way to do this is to add a boolean active column to your Customers table
create table Customers (
firstname varchar(20),
secondname varchar(20),
active Boolean default true
);
And then when you select your records
select * from Customers where active = true;
Then, rather than deleting entries from your customers table, you can just set active to false
Use “soft delete”. That means you don’t really ever delete anything, instead have a flag on each row you can toggle to show a customer is not active. Then you can have a view that shows only non-deleted customers that the code not concerned with undeleting can use.
You should be taking database backups.
Backups are your "first line of defense" - against accidental deletions ... and against anything else that could happen (like a hard disk crash, for example. Or a meteor crash.).
Another approach is to assign a [trigger] to any delete (or, for that matter, to "insert" and "update" statements as well). You can prevent deletion (if you wish), and you'll have a record of who tried to delete.
Here is an example: http://rpbouman.blogspot.com/2011/10/mysql-hacks-preventing-deletion-of.html
Finally, the best approach might be to never delete at all: just create a new "status" column. Set the initial value to "ACTIVE", and "deleted" value to "DELETED".
I agree totally with what #paulsm4 wrote.
I would also add that you could consider using Hibernate Envers.
Envers will create new tables that will record the changing state of audited tables.
An approach is to not actually delete the customer and add an additional status column.
In the business layer you will be able to display all users with status != DELETED.
OBS:
If you actually need to delete them from the database, you can make a cron that will scan all customers with status deleted and deletes them after x days.
I am running java application with multiple threads those will query from oracle database and if condition meets it will update row. But there are high chances that multiple threads gets same status for a row and then multiple thread try to update same row.
Lets say if status is "ACCEPTED" for any row then update it to "PROCESSING" status and then start processing, But processing should be done by only one thread who updated this record.
One approach is I query database and if status is "ACCEPTED" then update record, I need to write synchronized java method, but that will block multi-threading. So I wanted to use sql way for this situation.
Hibernate update method return type is void. So there is no way I can find if row got updated now or it was already updated. Is there any Select for Update or any locking thing in hibernate that can help me in this situation.
You can very well make use of Optimistic Locking through #Version.
Please look at the post below:
Optimistic Locking by concrete (Java) example
I think that your question is related to How to properly handle two threads updating the same row in a database
On top of this I woud say on top of the answer provided by #shankarsh that if you want to use a Query and not the entitymanager or the hibernate session you need to include the version field in your query like this:
update t.columntoUpdate,version = version + 1 from yourEntity where yourcondition and version = :version
This way the update will succeed only for a particular version and all the concurent updates will not update anything.
My Use Case:
my Hibernate configuration using auto increment generator for insert and I don't want to change it.
A user deleted a object with ID:10 and I saved this deleted object to somewhere.
later on, user decide to restore this deleted object back with the same ID:10.
since this object with ID:10 has been deleted from the database, How can I use Hibernate to insert it back to database while the hibernate configuration using auto increment generator(remember: I need keep the same ID for this object in database)?
Thanks,
Alex
I doubt Hibernate will let you do it if you don't change the generator. What about inserting it and then updating it with direct SQL and invalidating any hibernate caches?
I doubt Hibernate will not allow you to do this. However you can go and write sql queries to update Tables [If you have used Table Generator] to change the current index position that can be used but it will hell of complicated logic since you will always have to keep track on which index record is not present
There is a UNIQUE database constraint on an index which doesn't allow more than one record having identical columns.
There is a piece of code, managed by Hibernate (v2.1.8), doing two DAO
getHibernateTemplate().save( theObject )
calls which results two records entered into the table mentioned above.
If this code is executed without transactions, it results INSERT, UPDATE, then another INSERT and another UPDATE SQL statements and works fine. Apparently, the sequence is to insert the record containing DB NULL first, and then update it with the proper data.
If this code is executed under Spring (v2.0.5) wrapped in a single Spring transaction, it results two INSERTS, followed by immediate exception due to UNIQUE constraint mentioned above.
This problem only manifests itself on MS SQL due to its incompatibility with ANSI SQL. It works fine on MySQL and Oracle. Unfortunately, our solution is cross-platform and must support all databases.
Having this stack of technologies, what would be your preferred workaround for given problem?
You could try flushing the hibernate session in between the two saves. This may force Hibernate to perform the first update before the second insert.
Also, when you say that hibernate is inserting NULL with the insert, do you mean every column is NULL, or just the ID column?
I have no experience in Hibernate, so I don't know if you are free to change the DB at your will or if Hibernate requires a specific DB structure you cannot change.
If you can make changes then you can use this workaround in MSSQL tu emulate the ANSI behaviour :
drop the unique index/constraint
define a calc field like this:
alter table MyTable Add MyCalcField as
case when MyUniqueField is NULL
then cast(Myprimarykey as MyUniqueFieldType)
else MyUniqueField end
add the unique constraint on this new field you created.
Naturally this applies if MyUniqueField is not the primary key! :)
You can find more details in this article at databasejournal.com