I am using spring-hibernate-postgres. I have a table say 'some_entity'. It already contains some records.
I have a program that tries to create new SomeEntity object. I am populating that object with appropriate properties, and afterwards I am calling persist() method on it.
In the log, I see that hibernate is trying to get nextVal() from the table sequences. But, nextval that my postgres returns is same as id of 2nd row of some_entity table. So, my hibernate tries to create row with that id. And hence my persist() fails with hibernate constraint violation exception.
May be I am not phrasing the question correctly. I hope someone has already encountered this problem and has resolution for it.
Thanks
I had this problem. I solved it through execution of sql, that updates sequence at application launch
ALTER SEQUENCE names_id_seq RESTART WITH currentId;
,where currentId I get from
SELECT currval('names_id_seq');
Related
I am new to Hibernate, I could see that Hibernate throws StaleObjectStateException while multiple users trying to persist the complete entity. But, Most of the DB updates I have done using HQL update query. Now, I have added an extra condition to the HQL update queries as 'where version = :currentVersion' to identify no other user updated the particular record. It seems to be working fine. But, problem is that I have many number of queries and I also have to synchronize the version number in my java object as same in DB. Is there any simple way to get 'StaleObjectStateException' on HQL query update during multi user updates?
You understood this wrong. Hibernate throws StaleObjectStateException as a wanted behaviour for "while multiple users trying to persist the complete entity". This prevents that the last writer wins and overrides the data from his antecessors. Usually you catch this Exception and show some Error Message to the User like "Someone has changed the Data. Please Retry!". Your HQL query clause is the wrong way and will force you to patch your code even more and more.
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
is there a way that i get back the number of affected rows by using:
getHibernateTemplate().save(bean);
what is the point using save if you dont know what happened in the end.
Or, if i insert a new row, i want to get the new PK AI that was created....
Any idea?
Thanls
is there a way that i get back the number of affected rows by using:
Not for the "save" operation, which is quite understandable. But if you are using a Query, the executeUpdate method returns the number of affected records.
what is the point using save if you dont know what happened in the end.
Well, if there's no exception, you can assume everything went as expected.
Or, if i insert a new row, i want to get the new PK AI that was created....
Hibernate updates the persisted bean with the generated PK. So, if your bean has a long id, set with auto-increment, Hibernate will populate this field once it gets persisted.
I am looking for a way to save or update records, according to the table's unique key which is composed of several columns).
I want to achieve the same functionality used by INSERT ... ON DUPLICATE KEY UPDATE - meaning to blindly save a record, and have the DB/Hibernate insert a new one, or update the existing one if the unique key already exists.
I know I can use #SQLInsert( sql="INSERT INTO .. ON DUPLICATE KEY UPDATE"), but I was hoping not to write my own SQLs and let Hibernate do the job. (I am assuming it will do a better job - otherwise why use Hibernate?)
Hibernate may throw a ConstraintViolationException when you attempt to insert a row that breaks a constraint (including a unique constraint). If you don't get that exception, you may get some other general Hibernate exception - it depends on the version of Hibernate and the ability of Hibernate to map the MySQL exception to a Hibernate exception in the version and type of database you are using (I haven't tested it on everything).
You will only get the exception after calling flush(), so you should make sure this is also in your try-catch block.
I would be careful of implementing solutions where you check that the row exists first. If multiple sessions are updating the table concurrently you could get a race condition. Two processes read the row at nearly-the-same time to see if it exists; they both detect that it is not there, and then they both try to create a new row. One will fail depending on who wins the race.
A better solution is to attempt the insert first and if it fails, assume it was there already. However, once you have an exception you will have to roll back, so that will limit how you can use this approach.
This doesn't really sound like a clean approach to me. It would be better to first see if an entity with given key(s) exists. If so, update it and save it, if not create a new one.
EDIT
Or maybe consider if merge() is what you're looking for:
if there is a persistent instance with the same identifier currently associated with the session, copy the state of the given object onto the persistent instance
if there is no persistent instance currently associated with the session, try to load it from the database, or create a new persistent instance
the persistent instance is returned
the given instance does not become associated with the session, it remains detached
< http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html
You could use saveOrUpdate() from Session class.
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