Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

前端 未结 17 1845
别跟我提以往
别跟我提以往 2020-12-02 16:36

I have a java project that runs on a webserver. I always hit this exception.

I read some documentation, and found that pessimistic locking (or optimistic, but I read

相关标签:
17条回答
  • 2020-12-02 16:53

    Pessimistic locking is generally not recommended and it's very costly in terms of performance on database side. The problem that you have mentioned (the code part) a few things are not clear such as:

    • If your code is being accessed by multiple threads at the same time.
    • How are you creating session object (not sure if you are using Spring)?

    Hibernate Session objects are NOT thread-safe. So if there are multiple threads accessing the same session and trying to update the same database entity, your code can potentially end up in an error situation like this.

    So what happens here is that more than one thread tries to update the same entity, one thread succeeds and when the next thread goes to commit the data, it sees that its already been modified and ends up throwing StaleObjectStateException.

    EDIT:

    There is a way to use Pessimistic Locking in Hibernate. Check out this link. But there seems to be some issue with this mechanism. I came across posting a bug in hibernate (HHH-5275), however. The scenario mentioned in the bug is as follows:

    Two threads are reading the same database record; one of those threads should use pessimistic locking thereby blocking the other thread. But both threads can read the database record causing the test to fail.

    This is very close to what you are facing. Please try this if this does not work, the only way I can think of is using Native SQL queries where you can achieve pessimistic locking in postgres database with SELECT FOR UPDATE query.

    0 讨论(0)
  • 2020-12-02 16:53

    check if the object exists or not in DB, if it exists get the object and refresh it:

    if (getEntityManager().contains(instance)) {
        getEntityManager().refresh(instance);
        return instance;
    }
    

    if it fails the above if condition... find the Object with Id in DB, do the operation which you need, in this case exactly changes will reflects.

    if (....) {
        } else if (null != identity) {
            E dbInstance = (E) getEntityManager().find(instance.getClass(), identity);
            return dbInstance;
        }
    
    0 讨论(0)
  • 2020-12-02 16:53

    In order to prevent StaleObjectStateException, in your hbm file write below code:

    <timestamp name="lstUpdTstamp" column="LST_UPD_TSTAMP" source="db"/>
    
    0 讨论(0)
  • 2020-12-02 16:53

    I had this problem in one of my apps, now, I know this is an old thread but here is my solution; I figured out by looking at the data inside the debugger that JVM actually didn't load it properly when Hibernate was trying to update the database (that is actually done in a different thread), so I added the keyword "volatile" to every field of the entities. It has some performance issues to do that but rather that than Heavy objects beeing thrown around...

    0 讨论(0)
  • 2020-12-02 16:54

    First check your imports, when you use session, transaction it should be org.hibernate and remove @Transactinal annotation. and most important in Entity class if you have used @GeneratedValue(strategy=GenerationType.AUTO) or any other then at the time of model object creation/entity object creation should not create id. final conclusion is if you want pass id filed i.e PK then remove @GeneratedValue from entity class.

    0 讨论(0)
  • 2020-12-02 16:55

    I also ran into this error when attempting to update an existing row after creating a new one, and spent ages scratching my head, digging through transaction and version logic, until I realised that I had used the wrong type for one of my primary key columns.

    I used LocalDate when I should have been using LocalDateTime – I think this was causing hibernate to not be able to distinguish entities, leading to this error.

    After changing the key to be a LocalDateTime, the error went away. Also, updating individual rows began to work as well – previously it would fail to find a row for updating, and testing this separate issue was actually what led me to my conclusions regarding the primary key mapping.

    0 讨论(0)
提交回复
热议问题