-->
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.  [ 9 posts ] 
Author Message
 Post subject: Does a dyamic-class assume java.util.Map?
PostPosted: Sat Aug 28, 2004 11:34 am 
Regular
Regular

Joined: Mon Feb 23, 2004 10:42 pm
Posts: 102
Location: Washington DC
When declaring a dynamic-class in the mapping file, is it assumed that the underlying storage mechanism is a java.util.Map? It almost seems as if there should be a call to the interceptor to determine the entityName.

AbstractEntityPersister.isInstance() method
Code:
public boolean isInstance(Object object) {
      if (isDynamic) {
         return (object instanceof Map) &&
            entityName.equals( ( (Map) object ).get("type") );
      }
      else {
         return mappedClass.isInstance(object);
      }
   }



Hibernate version:
3.0 alpha

Mapping documents:
<hibernate-mapping>
<dynamic-class entity-name="person" table="person">
<id name="id" column="id" type="long" unsaved-value="0" access="org.progeeks.meta.hibernate.MetaObjectAccessor">
<generator class="native">
<param name="sequence">person_seq</param>
</generator>
</id>

<property name="firstName"
column="first_name"
type="string"
length="50"
insert="true"
update="true"
access="org.progeeks.meta.hibernate.MetaObjectAccessor"/>
</hibernate-mapping>

My custom PropertyAccessor
Code:
public class MetaObjectAccessor implements PropertyAccessor {

    static final Log log = Log.getLog( MetaObjectAccessor.class );

    /**
     * Creates a Getter for this named attribute.
     */
    public Getter getGetter( Class theClass, String propertyName ) throws PropertyNotFoundException
    {
        return new MetaObjectGetter( propertyName );
    }

    /**
     * Creates a Setter for this named attribute
     */
    public Setter getSetter( Class theClass, String propertyName ) throws PropertyNotFoundException
    {
        return new MetaObjectSetter( propertyName );
    }

    private final class MetaObjectSetter implements Setter {

        private String propertyName;

        public MetaObjectSetter( String propertyName )
        {
            this.propertyName = propertyName;
        }

        public void set( Object target, Object value ) throws HibernateException
        {
            if ( target != null && target instanceof MetaObject )
                {
                MetaObject metaObject = ( MetaObject ) target;
                if ( log.isDebugEnabled() )
                    log.debug( "Setting field [" + propertyName + "] to " + value );

                metaObject.setProperty( propertyName, value );
                }
        }

        public String getMethodName()
        {
            return null;
        }

        public Method getMethod()
        {
            return null;
        }
    }

    private final class MetaObjectGetter implements Getter {

        private String propertyName;

        public MetaObjectGetter( String propertyName )
        {
            this.propertyName = propertyName;
        }

        public Object get( Object target ) throws HibernateException
        {
            if ( target != null && target instanceof MetaObject )
                {
                MetaObject metaObject = ( MetaObject ) target;
                return metaObject.getProperty( propertyName );
                }

            return null;
        }

        public Class getReturnType()
        {
            return Object.class;
        }

        public String getMethodName()
        {
            return null;
        }

        public Method getMethod()
        {
            return null;
        }
    }

}




My custom Interceptor
Code:
/**
* An interceptor that allows Hibernate to create MetaObjects when loading
* data from the database.
*
*/
public class MetaObjectInterceptor implements Interceptor {

    static Log log = Log.getLog( MetaObjectInterceptor.class );

    private MetaKit metaKit;

    /**
     * Creates a new MetaObjectInterceptor that will use a MapMetaKit
     * as its underlying meta-object implementation layer.
     */
    public MetaObjectInterceptor()
    {
        this( new MapMetaKit( null ) );
    }

    /**
     * Creates a new MetaObjectInterceptor that will use the specified
     * MetaKit as its underlying meta-object implementation layer.
     */
    public MetaObjectInterceptor( MetaKit metaKit )
    {
        this.metaKit = metaKit;
    }

    /**
     * Creates an instance of a MetaObject with a given name.
     */
    public Object instantiate( String entityName, Serializable serializable ) throws CallbackException
    {
        MetaClass metaClass = MetaClass.forName( entityName );
        MetaObjectFactory factory = metaKit.getMetaObjectFactory();
        MetaObject metaObject = factory.createMetaObject( metaClass );

        // FIXME:
        // Until Hibernate fixes the Interceptor interface to include the EntityPersister
        // in the instantiate method, we need depend on the identity field in the meta
        // configuration
        Set identityProperties = metaObject.getMetaClass().getIdentityProperties();
        if( identityProperties.size() == 0 )
            {
            log.warn( "No identifiers defined for this metaClass [" + entityName + "]" );
            }

        if( identityProperties.size() == 1 )
            {
            String identityProperty = ( String ) identityProperties.toArray()[0];
            metaObject.setProperty(identityProperty , serializable );
            }

        if( identityProperties.size() > 1 )
            {
            log.warn( "Multiple identity properties defined for metaClass [" + entityName + "]" );
            }

        return metaObject;
    }

    /**
     * Returns the entityName of this object (type attribute's value).
     */
    public String getEntityName( Object o ) throws CallbackException
    {
        MetaObject metaObject = ( MetaObject ) o;
        return metaObject.getMetaClass().getName();
    }

    public boolean onLoad( Object o, Serializable serializable, Object[] objects, String[] strings, Type[] types ) throws CallbackException
    {
        return false;
    }

    public boolean onFlushDirty( Object o, Serializable serializable, Object[] objects, Object[] objects1, String[] strings, Type[] types ) throws CallbackException
    {
        return false;
    }

    public boolean onSave( Object o, Serializable serializable, Object[] objects, String[] strings, Type[] types ) throws CallbackException
    {
        return false;
    }

    public void onDelete( Object o, Serializable serializable, Object[] objects, String[] strings, Type[] types ) throws CallbackException
    {

    }

    public void preFlush( Iterator iterator ) throws CallbackException
    {

    }

    public void postFlush( Iterator iterator ) throws CallbackException
    {

    }

    public Boolean isUnsaved( Object o )
    {
        return null;
    }

    public int[] findDirty( Object o, Serializable serializable, Object[] objects, Object[] objects1, String[] strings, Type[] types )
    {
        return new int[0];
    }

    public Object getEntity( String s, Serializable serializable ) throws CallbackException
    {
        return null;
    }

}
[/code]

_________________
Matt Veitas


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 28, 2004 11:35 am 
Regular
Regular

Joined: Mon Feb 23, 2004 10:42 pm
Posts: 102
Location: Washington DC
I would have entered this in JIRA but that is currently down.

_________________
Matt Veitas


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 28, 2004 11:37 am 
Regular
Regular

Joined: Mon Feb 23, 2004 10:42 pm
Posts: 102
Location: Washington DC
Code:
Code:
Query query = session.createQuery( "from person" );
Iterator results = query.iterate();
while ( results.hasNext() )
   {
        log.info( results.next() );
        }

query = session.createQuery( "from person" );
List resultsList = query.list();
for ( Iterator iterator = resultsList.iterator(); iterator.hasNext(); )
   {
        log.info( iterator.next() );
        }


Log:
Hibernate: select person0_.id as col_0_0_ from person person0_
Hibernate: select person0_.id as id0_, person0_.first_name as first_name0_0_, person0_.last_name as
last_name0_0_, person0_.age as age0_0_ from person person0_ where person0_.id=?
Hibernate: select person0_.id as id0_, person0_.first_name as first_name0_0_, person0_.last_name as
last_name0_0_, person0_.age as age0_0_ from person person0_ where person0_.id=?
(INFO ) SimpleCacheTest - MapMetaObject[ map={age=26, firstName=Matt, id=1, lastName=Veitas} ]
(INFO ) SimpleCacheTest - MapMetaObject[ map={age=33, firstName=Al, id=2, lastName=Veitas} ]
Hibernate: select person0_.id as id, person0_.first_name as first_name0_, person0_.last_name as last
_name0_, person0_.age as age0_ from person person0_


Exception being thrown:
Exception in thread "main" org.hibernate.WrongClassException: Object with id: 1 was not of the speci
fied subclass: person (loaded object was of wrong class)
at org.hibernate.loader.Loader.instanceAlreadyLoaded(Loader.java:663)
at org.hibernate.loader.Loader.getRow(Loader.java:612)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:248)
at org.hibernate.loader.Loader.doQuery(Loader.java:337)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:167)
at org.hibernate.loader.Loader.doList(Loader.java:1201)
at org.hibernate.loader.Loader.list(Loader.java:1186)
at org.hibernate.hql.QueryTranslatorImpl.list(QueryTranslatorImpl.java:872)
at org.hibernate.impl.SessionImpl.find(SessionImpl.java:812)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:84)
at com.osc.hibernate.cache.SimpleCacheTest.runTest(SimpleCacheTest.java:42)
at com.osc.hibernate.cache.SimpleCacheTest.main(SimpleCacheTest.java:59)[/b]

_________________
Matt Veitas


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 28, 2004 1:16 pm 
Regular
Regular

Joined: Mon Feb 23, 2004 10:42 pm
Posts: 102
Location: Washington DC
I was able to handle the error by creating my own custom EntityPersister. Still looking for answer regarding if dynamic-class assumes if the underlying object is to be a Map.

Code:
public class SimpleMetaObjectPersister extends SingleTableEntityPersister
{
    static Log log = Log.getLog( SimpleMetaObjectPersister.class );

    public SimpleMetaObjectPersister( PersistentClass persistentClass,
                                      CacheConcurrencyStrategy cacheStrategy,
                                      SessionFactoryImplementor factory )
    {
        super( persistentClass, cacheStrategy, factory );
    }

    public boolean isInstance( Object object )
    {
        MetaObject metaObject = ( MetaObject ) object;
        return metaObject.getMetaClass().getName().equals( getEntityName() );
    }
}

_________________
Matt Veitas


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 28, 2004 7:40 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Yes, a dynamic-class is a mapping for a Map.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 28, 2004 11:33 pm 
Regular
Regular

Joined: Mon Feb 23, 2004 10:42 pm
Posts: 102
Location: Washington DC
Then what is the perferred method for using a custom persistent object, something that is not a bean or a map? Should the mapping be, <dynamic-class> or <class>?

I have had create an interceptor, property accessor, as well as override the entity persister to make everything work so far.

_________________
Matt Veitas


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 28, 2004 11:37 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
use <class> as the mapping. You would need your own:

PropertyAccessor
EntityPersister
ProxyFactory, perhaps

should not need an Interceptor, i would not have thought...

(You are the first person to try this new functionality, so please give us lots of feedback.)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Aug 29, 2004 8:30 am 
Regular
Regular

Joined: Mon Feb 23, 2004 10:42 pm
Posts: 102
Location: Washington DC
Gavin,

Thanks for the feedback. I am going to start two new threads, (1)dynamic-class vs class and (2)Using custom persistent objects for this discussion or is this better suited for the developer list?

After we finish up the discussions, it might be a useful to post something to the docs or FAQ: dynamic-class vs class.

_________________
Matt Veitas


Top
 Profile  
 
 Post subject:
PostPosted: Sun Aug 29, 2004 8:40 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
I guess it can stay here.

Note that I did some work on the dynamic-class stuff today and a couple of days ago and it is in CVS.


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