-->
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.  [ 8 posts ] 
Author Message
 Post subject: custom persister problem
PostPosted: Wed Nov 19, 2003 5:32 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Hello.

I have Organization class and couple of its <joined-subclass>es (say Company and Client). Everything worked fine until I specified custom persister for Organization class

Now I'm getting

Code:
net.sf.hibernate.MappingException: discriminator mapping required for polymorphic persistence
   at net.sf.hibernate.persister.EntityPersister.<init>(EntityPersister.java:767)
   at com.dataart.audit.AuditableEntityPersister.<init>(AuditableEntityPersister.java:23)
   at java.lang.reflect.Constructor.newInstance(Native Method)
   at net.sf.hibernate.persister.PersisterFactory.create(PersisterFactory.java:75)
   at net.sf.hibernate.persister.PersisterFactory.createClassPersister(PersisterFactory.java:47)
   at net.sf.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:136)
   at net.sf.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:718)


All other classes work with this persister just fine. Persister is very simple subclass of EntityPersister with overloaded findDirty method. Constructor just calls super(...)

What is wrong?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 19, 2003 9:07 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
anyone?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 12:59 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Well, I'm not sure how you expect us to help you without showing any mappings, or the code of the custom persister.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 1:12 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Sorry...

Quick explanation first:
I'm trying to implement auditing much like described here: http://www.hibernate.org/48.html

The solution above has a big problem with findDirty() method (this method is not implemented at all, but there is some implementation in "comments") - it converts objects from currentState/previousState arrays to strings in order to check if state has changed. I wanted to use "standard" Hibernate dirty check and add AuditInfo property to list of dirty if Hibernate states there is at leas one dirty property for an object. I hae found only one way of doing this - using persister:

Persister's

Code:
public class AuditableEntityPersister extends EntityPersister
{
    public AuditableEntityPersister(PersistentClass model, SessionFactoryImplementor factory) throws HibernateException
    {
        super(model, factory);
    }

    public int[] findDirty(Object[] currentState,
                           Object[] previousState,
                           Object object,
                           SessionImplementor session)
            throws HibernateException
    {
        int[] dirty = super.findDirty(currentState, previousState, object, session);

        if (dirty == null)
            return null;

        if (!(object instanceof Auditable))
            return dirty;

        Type[] types = getPropertyTypes();

        int auditInfoIndex = -1;
        for (int index = 0; index < types.length; index++)
        {
            Class propertyClass = types[index].getReturnedClass();
            if (AuditInfo.class.isAssignableFrom(propertyClass))
            {
                // AuditInfo property
                auditInfoIndex = index;
            }
        }

        if (auditInfoIndex == -1)
            throw new RuntimeException("Auditable class " + object.getClass().getName() +
                                       " does not contain property of type AuditInfo");

        // If we have not found AuditInfo property, do nothing additional
        if (auditInfoIndex == -1)
            return dirty;

        // Check if our AuditInfo is among dirty properties
        for (int index = 0; index < dirty.length; index++)
        {
            int column = dirty[index];

            if (column == auditInfoIndex)
            {
                // Audit info is among dirty properties
                // It will be saved by Hybernate and without our intervention

                return dirty;
            }
        }

        // There are dirty properties but AuditInfo is not dirty

        int[] extendedDirty = new int[dirty.length + 1];
        System.arraycopy(dirty, 0, extendedDirty, 0, dirty.length);

        // Mark AuditInfo property dirty
        extendedDirty[dirty.length] = auditInfoIndex;

        return extendedDirty;
    }

}


The mapping (truncated):

Code:
    <class name="Organization"
           table="ORGANIZATION"
           proxy="Organization"
           persister="AuditableEntityPersister">

...
        <joined-subclass
            name="Client"
            table="CLIENT"
            proxy="Client">
..
        </joined-subclass>


        <joined-subclass
            name="Company"
            table="COMPANY"
            proxy="Company">
...
        </joined-subclass>
...
</class>



I'm just not sure which part of mapping is meaningful for you and entire mapping is big enough.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 5:41 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Things mapped with <joined-subclass> would need to extend NormalizedEntityPersister.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 8:38 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Oh... Thanks Gavin, this solved the problem.

But now I have two persisters - AuditableEntityPersister and AuditableNormalizedEntityPersister. And I have to remember which one should I use for which class. Not a most elegant way definitely...

Is there a better way? Or may be you think this idea of maintaining audit info is just flawed and something different must be used? In other words, if you need to add audit info to many classes, which direction would you start thinking in?

Thanks again.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 8:40 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
http://www.hibernate.org/Documentation/ ... CustomType

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 21, 2003 9:09 pm 
Expert
Expert

Joined: Tue Sep 16, 2003 4:06 pm
Posts: 318
Location: St. Petersburg, Russia
Thanks, Christian, but this is what I'm actually trying to improve :)

My code is based on AuditInfo custom type. I have already explained problems with the original version: it does not implement findDirty method (that means it is for very old version of Hibernate). There are user comments right after tha article you pointed me on and one of them ( http://www.hibernate.org/48.43.html implements findDirty ). The idea very simple - if any of properties modified, return all these properties plus AuditInfo property to enforce its update. But the problem is dirty check - the guy who wrote findDirty implementation uses followinf construct:

Code:
if(previous.toString().equals(current.toString()))


This sucks big time. What I need is to let Hibernate to perform dirty check itself and then be able to modify result - if one of properties is dirty, make AuditInfo property dirty as well.

And the only way I have found to let Hibernate perform dirty check and be able to modify result is by extending EntityPersister

But this thing becomes way too complex - Interceprot, user type, two persisters...[/code]


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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.