-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: How to prevent updates for unchanged entities
PostPosted: Wed Mar 15, 2017 1:22 pm 
Newbie

Joined: Wed Mar 15, 2017 1:03 pm
Posts: 6
Using hibernate 5.2.2 and DB2 LUW 10.5.

Inside of a transactional persistence context, there is an entity that is loaded via query and never changed, but then hibernate performs an UPDATE for this entity. This is a simple transaction involving two classes A and B. Class A is the class of the instance that gets the unwanted UPDATE. Class A has a generated ID strategy:

Code:
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Integer id;


Class B has an association to A:

Code:
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "A_ID")
    private A myA;


But there is no reverse @OneToMany collection mapping in class A.

These are the specific steps:

1. Start the transaction
2. Call EntityManager.find(id) to load entity A1 of class A
3. Create new entity instance B1 of class B
4. Set B1.myA = A1
5. Call EntityManager.persist(B1)
6. Commit the transaction

Hibernate performs INSERT for B1, but also performs unwanted UPDATE for A1. Is there any way to prevent hibernate performing the UPDATE of A1?


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Wed Mar 15, 2017 3:28 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
No, it shouldn't. Try replicating it with a test case, and I'll take a look on it.


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Thu Mar 16, 2017 9:01 am 
Newbie

Joined: Wed Mar 15, 2017 1:03 pm
Posts: 6
Good to hear that hibernate should not be expected to perform this unwanted UPDATE. I am working from production system log output and looking at the code. Wanted to know if there was some way to explicitly tell hibernate not to update some entity in the persistence context. Note that both entity classes also have version fields for optimistic locking, like:

@Version
@Column(name = "VERSION")
public Integer version = 1;

Not sure if there could be some issue with hibernate implicitly incrementing the version and that causing the entity to be updated, even though the entity is has not been updated in any other way. I would not expect this to be the case, but I'm not making any assumptions at this point.

Let me try to replicate the issue locally, then I will reply again.

Thanks,
Greg


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Thu Mar 16, 2017 10:22 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Without seeing your code, I suspect you are overwriting collections with a setter instead of using the getter and manipulating the content. Is that true?


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Thu Mar 16, 2017 12:04 pm 
Newbie

Joined: Wed Mar 15, 2017 1:03 pm
Posts: 6
There are no collections involved in this transaction. It really is about as simple as what I posted originally. The symptom indicated by the logs is that the transaction fails with an OptimisticLockException on A1, when we did not modify A1. We only created B1 and set the ManyToOne association of B1 to A1. The OptimisticLockException indicates that hibernate must have attempted an UPDATE for A1.

Let me reproduce this locally and confirm that hibernate is actually performing an UPDATE for A1, in addition to the desired INSERT for B1. I will attempt to reproduce/confirm today, then reply again.


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Thu Mar 16, 2017 4:13 pm 
Newbie

Joined: Wed Mar 15, 2017 1:03 pm
Posts: 6
I confirmed that hibernate does execute both the necessary INSERT of B1 and also the unnecessary UPDATE of A1 in this transaction.

Vlad, in order for you to investigate further, do I need to reproduce via a test case, per the link that you provided? Can you think of any reason why this might be happening?

Greg


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Thu Mar 16, 2017 4:44 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
The update is triggered only if the dirty checking mechanism has detected a change. You'll have to debug the DefaultFlushEventListener and see which property triggers the UPDATE to be scheduled.


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Tue Mar 21, 2017 10:18 am 
Newbie

Joined: Wed Mar 15, 2017 1:03 pm
Posts: 6
I found time for the debugging. I think you were going in the right direction in mentioning collections. There are two dirty fields on our entity. Both are Map<String, String> that we map with a custom org.hibernate.usertype.UserType. Each field maps a DB2 XML column, and we carry as Map<String, String> in the entity class. I suppose there must be something about how we load the value from DB2 to the entity object via the UserType, and this causes hibernate to think the field is dirty. Can you tell me some guidelines as to what we should do in the UserType, to avoid this issue? Can you point me to some article/documentation?

Thanks,
Greg


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Tue Mar 21, 2017 10:53 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
One option is to make the immutable as stated in this article. This way, only if you set the Map explicitly, it will become dirty and Hibernate will propagate the state changes.

Otherwise, just make sure you implement the following methods properly:

Code:
boolean equals(Object x, Object y);

int hashCode(Object x);

Object deepCopy(Object value);

boolean isMutable();

Serializable disassemble(Object o);

Object assemble(
        Serializable cached,
        Object owner) {
        return cached;
};

Object replace(
        Object o,
        Object target,
        Object owner);


Run a debug and see if any of these methods is causing Hibernate to schedule an update.


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Tue Mar 21, 2017 12:18 pm 
Newbie

Joined: Wed Mar 15, 2017 1:03 pm
Posts: 6
Thanks for your help. I found the issue and tested the fix. In a shared superclass for user types, we had some default method implementations, including:

Code:
    @Override
    public boolean equals(Object value1, Object value2) throws HibernateException {
        return value1 == value2;
    }

I think our first custom user types were for enums, so this worked fine for that. Does not work for collections. Hibernate calls deepCopy() to cache the initial field state, and we create/return a new Map. Will never compare as "equal" using == to the Map held by the entity. So the entity will always be considered dirty. Changed to:

Code:
    @Override
    public boolean equals(Object value1, Object value2) throws HibernateException {
        return ObjectUtils.nullSafeEquals(value1, value2);
    }

and now is working as desired.

Thanks again,
Greg


Top
 Profile  
 
 Post subject: Re: How to prevent update of unchanged entities
PostPosted: Tue Mar 21, 2017 1:17 pm 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
I'm glad you found the issue and that it works now.


Top
 Profile  
 
 Post subject: Re: How to prevent updates for unchanged entities
PostPosted: Thu Apr 13, 2017 11:07 am 
Newbie

Joined: Sat Apr 08, 2017 6:03 pm
Posts: 1
gb5600 I had a very similar problem and I just managed to fix that because of your topic! Thanks


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.