-->
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.  [ 5 posts ] 
Author Message
 Post subject: Polymorphic association not persisting correctly
PostPosted: Wed Oct 17, 2007 1:46 pm 
Newbie

Joined: Tue Dec 05, 2006 2:47 am
Posts: 9
3,2,4,GA

I am having a problem with a polymorphic association in dynamic-map mode. I have the following structure:


Document.get( "lines" ) is a one-to-many to DocumentLine's
BidDocument extends Document
BidDocument.get( "lines" ) is a one-to-many to BidDocumentLine's

I declare the association in Document using the following:
Code:
        <set name="lines" inverse="true" cascade="all-delete-orphan" lazy="true">
            <key column="document_id"/>
            <one-to-many entity-name="DocumentLine"/>
        </set>


And the inverse relation in DocumentLine
Code:
         <many-to-one name="document" column="document_id" entity-name="Document" lazy="proxy"/>


There is no corresponding association in BidDocument or BidDocumentLine.

I populate a BidDocument with BidDocumentLines and then persist the BidDocument. All the BidDocument related information is persisted to the hierarchy just fine, but the BidDocumentLines are persisted as DocumentLines. IE: There is a row created for each DocumentLine, but no rows in the BidDocumentLine table.

I have tried <joined-subclass> as well as <subclass><join> with a discriminator but no avail, same problem.

I have tried to set the $type$ key on the map to see if that will help but when looking at the source code it seems that key is only used to indicate the type before passing it to the user, not to determine at runtime how to persist the map (like an implicit discriminator maybe?)

Can I override a method in the EntityPersister to force hibernate to persist the Map as a specific entity-name? Or how can I get the desired behavior without doing this? I would like to use <joined-subclass> if possible

Mapping documents and code follow:

Document.hbm.xml
Code:
<hibernate-mapping>
    <joined-subclass entity-name="Document" extends="Base" table="document">

        <tuplizer class="org.hibernate.tuple.entity.HibernateEntityMapTupilizer"
                  entity-mode="dynamic-map"/>

       
        <key column="id"/>

        <property name="name" type="string" column="name"/>
        <property name="companyName" type="string" column="company_name"/>
        <property name="reference" type="string" column="reference"/>
        <property name="customerReference" type="string" column="customer_reference"/>
        <property name="created" type="timestamp" column="created"/>
        <property name="modified" type="timestamp" column="modified"/>
        <property name="description" column="description" type="text"/>

        <many-to-one name="category" column="category_id" entity-name="Category" lazy="proxy"/>
       
        <many-to-one name="createdBy" column="employee_created_by_id" entity-name="Employee" lazy="proxy"/>
        <many-to-one name="modifiedBy" column="employee_modified_by_id" entity-name="Employee" lazy="proxy"/>

        <set name="lines" inverse="true" cascade="all-delete-orphan" lazy="true">
            <key column="document_id"/>
            <one-to-many entity-name="DocumentLine"/>
        </set>


    </joined-subclass>
</hibernate-mapping>




DocumentLine.hbm.xml
Code:
<hibernate-mapping>
    <joined-subclass entity-name="DocumentLine" extends="Base" table="document_line">

        <tuplizer class="org.hibernate.tuple.entity.HibernateEntityMapTupilizer"
                  entity-mode="dynamic-map"/>

        <key column="id"/>

        <many-to-one name="document" column="document_id" entity-name="Document" lazy="proxy"/>

    </joined-subclass>
</hibernate-mapping>




Bid.hbm.xml
Code:
<hibernate-mapping>
    <joined-subclass entity-name="Bid" extends="Document" table="bid">

        <key column="id"/>     

    </joined-subclass>
</hibernate-mapping>



BidLine.hbm.xml
Code:
<hibernate-mapping>
    <joined-subclass entity-name="BidLine" extends="DocumentLine" table="bid_line">

        <tuplizer class="org.hibernate.tuple.entity.HibernateEntityMapTupilizer"
                  entity-mode="dynamic-map"/>

        <key column="id"/>

        <property name="manufacturerSKU" type="string" column="manufacturer_sku"/>
        <property name="ediSKU" type="string" column="edi_sku"/>
        <property name="bidPrice" type="double" column="bid_price"/>
        <property name="askPrice" type="double" column="ask_price"/>
        <property name="quantity" type="integer" column="quantity"/>
        <property name="description" type="string" column="description"/>
       
    </joined-subclass>
</hibernate-mapping>



HibernateEntityMapTuplizer.java
Code:
public class HibernateEntityMapTupilizer extends DynamicMapEntityTuplizer
{
    private static Log log = LogFactory.getLog(HibernateEntityMapTupilizer.class);

    public HibernateEntityMapTupilizer( EntityMetamodel entityMetamodel, PersistentClass persistentClass )
    {
        super(entityMetamodel, persistentClass);

    }

    protected Instantiator buildInstantiator( final PersistentClass persistentClass )
    {
        return new DynamicMapInstantiator( persistentClass ) {
            protected Map generateMap()
            {
                return new Entity( persistentClass.getEntityName() );
            }
        };
    }

    public Class getMappedClass()
    {
        return Entity.class;
    }

}


main()
Code:
        SessionFactory sf = (SessionFactory)context.getBean( "sessionFactory" );
        Session session = sf.openSession();


        Transaction tx = session.beginTransaction();

        Entity bid = new Entity( "Bid" );
        bid.put( "name", "Bid Document #1" );

        Entity bidLine = new Entity( "BidLine" );
        bidLine.put( "description", "Product #1" );

        List list = new ArrayList( );
        list.add( bidLine );

        bid.put( "lines", list );
        bidLine.put( "document", bid );

        session.merge( "SonyBid", bid );

        tx.commit();
       
        System.out.println("Finished.");



Here is the log output:
Code:
DEBUG SQL - insert into document (name, company_name, reference, customer_reference, created, modified, description, category_id, employee_created_by_id, employee_modified_by_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into document (name, company_name, reference, customer_reference, created, modified, description, category_id, employee_created_by_id, employee_modified_by_id, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
DEBUG AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG SQL - insert into bid (id) values (?)
Hibernate: insert into bid (id) values (?)
DEBUG AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG SQL - insert into bid_sony (sony1, sony2, id) values (?, ?, ?)
Hibernate: insert into bid_sony (sony1, sony2, id) values (?, ?, ?)
DEBUG AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG SQL - insert into base (version, id) values (?, ?)
Hibernate: insert into base (version, id) values (?, ?)
DEBUG AbstractBatcher - Executing batch size: 1
DEBUG AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG SQL - insert into document_line (document_id, id) values (?, ?)
Hibernate: insert into document_line (document_id, id) values (?, ?)
DEBUG AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG AbstractBatcher - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
DEBUG SQL - update base set version=? where id=? and version=?
Hibernate: update base set version=? where id=? and version=?
DEBUG AbstractBatcher - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
DEBUG JDBCTransaction - re-enabling autocommit
DEBUG JDBCTransaction - committed JDBC Connection
DEBUG ConnectionManager - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
Finished.


And finally, the SQL results:
Code:
erp=> select * from document;
id |      name       | company_name | reference | customer_reference | created | modified | description | category_id | employee_created_by_id | employee_modified_by_id
----+-----------------+--------------+-----------+--------------------+---------+----------+-------------+-------------+------------------------+-------------------------
  1 | Bid Document #1 |              |           |                    |         |          |             |             |                        |
(1 row)

erp=> select * from document_line;
id | document_id
----+-------------
  2 |           1
(1 row)

erp=> select * from bid;
id
----
  1
(1 row)

erp=> select * from bid_line;
id | manufacturer_sku | edi_sku | bid_price | ask_price | quantity | description
----+------------------+---------+-----------+-----------+----------+-------------
(0 rows)





On another side note: why is DynamicMapEntityTuplizer package protected?

Hope this is enough information. I think it is just something stupid in my mapping files, but I can't seem to figure out what.


Top
 Profile  
 
 Post subject: can't subclass DynamicMapEntityTuplizer?
PostPosted: Mon Jun 02, 2008 4:14 pm 
Newbie

Joined: Wed May 28, 2008 5:55 pm
Posts: 5
Re: "why is DynamicMapEntityTuplizer package protected"

The class doesn't seem package protected, but its constructor is:

DynamicMapEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity) {
super(entityMetamodel, mappedEntity);
}

and this prevents subclassing DynamicMapEntityTuplizer, and that prevents using a different Map implementation than

HashMap, right?

Subclassing DynamicMapEntityTuplizer is mentioned at

http://www.hibernate.org/hib_docs/refer ... -tuplizers


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 02, 2008 4:22 pm 
Newbie

Joined: Tue Dec 05, 2006 2:47 am
Posts: 9
Yup,

I had to place my subclass in org.hibernate.tuple.entity package to get it to work.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 02, 2008 10:10 pm 
Newbie

Joined: Wed May 28, 2008 5:55 pm
Posts: 5
That means you added the .class files to the org/hibernate/tuple/entity subdirectory in hibernate3.jar, right? It works for me.

(In a separate Java project, I had tried making a package with an identical name and finally got it to compile but I get this at runtime:

Initial Hibernate SessionFactory creation failed - Could not build tuplizer [org.hibernate.mapping.PersistentClass.MyExampleTuplizer]
(and the details mention the constructor I have which is public))

Here's the code I came up with - more is needed than in the example at http://www.hibernate.org/hib_docs/refer ... -tuplizers

package org.hibernate.tuple.entity;

import org.hibernate.mapping.PersistentClass;
import org.hibernate.tuple.DynamicMapInstantiator;
import org.hibernate.tuple.Instantiator;

public class CustomMapTuplizer extends DynamicMapEntityTuplizer {

protected CustomMapTuplizer(EntityMetamodel entityMetamodel,
PersistentClass mappedEntity) {
super(entityMetamodel, mappedEntity);
}

// override the buildInstantiator() method to plug in our custom map...
protected final Instantiator buildInstantiator(
org.hibernate.mapping.PersistentClass mappingInfo) {
return new CustomMapInstantiator(mappingInfo);
}

private final class CustomMapInstantiator extends
DynamicMapInstantiator {

private static final long serialVersionUID = -8013096135820086811L;

protected CustomMapInstantiator(
org.hibernate.mapping.PersistentClass mappingInfo) {
super();
}

// override the generateMap() method to return our custom map...
protected final CustomMap generateMap() {
return new CustomMap();
}
}

}


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 03, 2008 12:28 pm 
Newbie

Joined: Tue Dec 05, 2006 2:47 am
Posts: 9
This is what I have-- but it it within my own project (not in hibernate3.jar), and it works fine:

Code:
package org.hibernate.tuple.entity;

/************************************************************************
*
*   This class is here because the DynamicMapEntityTyplizer has a
*   protected constructor and therefore needs to be in the same package.
*
************************************************************************/

/**
* #COPYRIGHT#
* <p/>
* User: hindog
* Date: Sep 13, 2007
* Time: 1:01:55 AM
*/
public class HibernateEntityMapTupilizer extends DynamicMapEntityTuplizer
{
    private static Log log = LogFactory.getLog(HibernateEntityMapTupilizer.class);

    public HibernateEntityMapTupilizer( EntityMetamodel entityMetamodel, PersistentClass persistentClass )
    {
        super(entityMetamodel, persistentClass);
    }

    protected Instantiator buildInstantiator( final PersistentClass persistentClass )
    {
        return new DynamicMapInstantiator( persistentClass ) {
            protected Map generateMap()
            {
                return new Entity( persistentClass.getEntityName() );
            }                       
        };
    }

    public boolean isInstrumented()
    {
        return false;
    }

    public Class getMappedClass()
    {
        return Entity.class;
    }

    @Override
    public Class getConcreteProxyClass()
    {
        return Entity.class;
    }

   
       
}


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