Issue Details (XML | Word | Printable)

Key: HV-281
Type: Bug Bug
Status: Open Open
Priority: Major Major
Assignee: Unassigned
Reporter: thogau
Votes: 2
Watchers: 3
Operations

If you were logged in you would be able to see more operations.
Hibernate Validator

validation of a persisted map

Created: 21/Jan/10 06:10 AM   Updated: Monday 03:23 PM
Component/s: engine
Affects Version/s: None
Fix Version/s: 4.1.0-Beta-1

Time Tracking:
Not Specified

File Attachments: 1. Zip Archive mapValidation.zip (1.22 MB)

Environment:
hibernate-core 3.5.0-Beta-3
Validator 4.0.1.GA
MySQL 5.1

Bug Testcase Reminder (view):
REMINDER: Bug reports should generally be accompanied by a test case
Participants: thogau and Vladimir Klyushnikov


 Description  « Hide

Hi,

I am trying to validate an entity that holds a Map<K, V> of other persisted entities (just checking wether the map holds some predefined values).
I can validate it "by hand" using validator.validate() and my map is correctly filled at validation time
However when validation framework is called by persistence callbacks, my map is always empty...
I am using Validator 4.0.1.GA and hibernate-core 3.5.0-Beta-2

I tryed to pinpoint the problem and it seems that the map is not touched in the following method of AbstractType during the merge :

public Object replace(
      Object original, Object target, SessionImplementor session,
      Object owner, Map copyCache, ForeignKeyDirection foreignKeyDirection) throws HibernateException {
   boolean include;
   if ( isAssociationType() ) {
      AssociationType atype = (AssociationType) this;
      include = atype.getForeignKeyDirection()==foreignKeyDirection;
   }
   else {
      include = ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT==foreignKeyDirection;
   }
   return include ? replace(original, target, session, owner, copyCache) : target;
}


Vladimir Klyushnikov added a comment - 03/Mar/10 04:10 AM

Hi,

I was struggling with this issue all past day. Bad news that this is behaviour by design and it is used to merge entities with collections of other entities that use assigned identifiers (IMHO). But it leads to really annoying problems. First is the issue that is mentioned in description and the second is that merging transient entity with collection executes INSERT and subsequent UPDATE of same entity. I use auditing of my entity and don't need this update.
Good news that I've found a simple workaround. It will work only with generated IDs and it is ok for me. I've developed a custom merge listener and registered it:

public class CollectionHandlingMergeEventListener extends DefaultMergeEventListener {

    @Override
    protected void copyValues(EntityPersister persister, Object entity, 
        Object target, SessionImplementor source,
        Map copyCache, ForeignKeyDirection foreignKeyDirection) {
        if (foreignKeyDirection != ForeignKeyDirection.FOREIGN_KEY_TO_PARENT) {
             Object[] copiedValues = TypeFactory.replace(
                    persister.getPropertyValues(entity, source.getEntityMode()),
                    persister.getPropertyValues(target, source.getEntityMode()),
                    persister.getPropertyTypes(),
                    source,
                    target,
                    copyCache
            );
            persister.setPropertyValues(target, copiedValues, source.getEntityMode());
        }
    }
}

Of course, it is a hack. Hope core contributors will find a better way to solve these issues.