-->
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.  [ 30 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Multiple 1-to-1's ending in 1-to-M and Foreign
PostPosted: Fri Nov 14, 2003 6:22 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
Hey guys, firstly, this isn't a "GIVF ANSWER NOW!!11" type question, but more a.."Is this actually supported?" type discussion.

I'll post the bare basics of my mappings below, and then discuss it.

XML:
Code:
<class name="cdl.impl.XMLImpl" table="XML">
    <id name="XMLID" column="XMLID" type ="java.lang.Long" unsaved-value="null">
        <generator class="identity"/>
    </id>

    <one-to-one name="Matter" class="cdl.impl.MatterImpl" cascade="all"/>

Matter:
Code:
<class name="cdl.impl.MatterImpl" table="Matter">
    <id name="XMLID" column="XMLID" type ="java.lang.Long" unsaved-value="null">
        <generator class="foreign">
            <param name="property">XML</param>
        </generator>
    </id>

    <one-to-one name="XML" class="cdl.impl.XMLImpl" constrained="true"/>
    <one-to-one name="Properties" class="cdl.impl.PropertiesImpl" />

Properties:
Code:
    <class name="cdl.impl.PropertiesImpl" table="Properties">
            <id name="XMLID" column="XMLID" type ="java.lang.Long" unsaved-value="null">
                <generator class="foreign">
                    <param name="property">Matter</param>
                </generator>
            </id>

            <one-to-one name="Matter" class="cdl.impl.MatterImpl" constrained="true"/>
        <bag name="Property" inverse="true" lazy ="false">
            <key column="XMLID" />
            <one-to-many class="cdl.impl.PropertyImpl" />
        </bag>
    </class>

Property:
Code:
<class name="cdl.impl.PropertyImpl" table="Property">
    <id name="PropertyID" column="PropertyID" type ="java.lang.Long" unsaved-value="null">
        <generator class="identity"/>
    </id>

    <property name="XMLID" column="XMLID" not-null="true"/>


Ok, so what we have there, is a 1-1, then another 1-1, then a 1-M.

As you can see, I do the cascade="all" at the first 1-1, but I cannot (can I?) do the cascade from there onwards. When I designed this originally, I switched the cascades on all the way through, but I started getting the null foreign key exception right at the bottom.

I tried many various things, but could never get the cascade to work all the way down. Te question is, does Hibernate support having multiple layers of Foreign key generators, including a bag (set) at the end?

This is a very unique situation for me, and I got it to work perfectly, by doing the child.setParent() way after the first cascade had saved.

As I said, just a discussion, my system works, but it would be nice to work out a way of making cascade work through multiple layers of Foreign generators. :)

-G


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 7:34 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
It should work the only doubt I have is how the "foreign" generator affects things.

I have never tried to use two layers of foreign generators before so I couldn't really say if it works.

Would you please do some further experiments with this and find out? What happens if you try to use "assigned" ids on all classes, for example?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 7:51 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
Hey Gavin, thanks for answerring, here's a little of how I handle the code...
(I read this in from an XML file, using JAXB)


Code:
matter = xml.getMatter();
Properties props = matter.getProperties();
List properties = props.getProperty();  //yes yes, confusing names... :P

// I then traverse the properties list manipulation various fields, till I get to here:

    property.setProperties(props);
    properties.set(i, property);  //create Child - Parent link
}
props.setProperty(properties);
matter.setProperties(props);

// after other child processing I get to this (probably redundant) bit of code
matter.setXML(xml);
xml.setMatter(matter);

session.saveOrUpdate(xml);
//...

// Then I do this:
    props = matter.getProperties();
    props.setXMLID(matter.getXMLID());
    for (int i=0; i < props.getProperty().size(); i++) {
        property = (Property) props.getProperty().get(i);
        property.setXMLID(matter.getXMLID());
        props.getProperty().set(i, property);
        property.setProperties(props);
        session.save(property);
    }
    props.setMatter(matter);
    matter.setProperties(props);
    session.save(props);

What is interesting, is that even though I have not put in cascade="all", when I save the Properties, it saves all its children.

I did try multiple ways of doing this...the very first version made use of 1-M, 1-M, but then an issue arose, that required a bridging 1-1 inbetween.

I must say, that my gut feeling is that two+ layered foreign generators don't work. I think I'll write a simplified verson of this to test completely, thoroughly, and utterly. :)

I'm modify my live code (assigned) quickly, and see what it does...I'll let you know when I have a result. Surely using assigned would break the one-to-one mapping?

-G


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 7:53 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
Ignore the "What is interesting..." line... :P

-G


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 8:04 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
Surely using assigned would break the one-to-one mapping?


Not if you assign the same ids :)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 8:11 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
gavin wrote:
Quote:
Surely using assigned would break the one-to-one mapping?


Not if you assign the same ids :)

Ok. Next question, doesn't this make the cascade somewhat useless?
Because I will still have to traverse through each of the children, and assign it its PK (ID) and all it will do is mean that I leave out the individual saves. Sure, it'll cascade, but it's not "true" one-to-one cascading is it? :)

I'm creating a much simpler version if it (leaving out all other fields) and I'll test it soon.

-G


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 8:26 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
Ok. Next question, doesn't this make the cascade somewhat useless?


Sure, but we are just trying to isolate the problem here!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 9:00 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
gavin wrote:
Sure, but we are just trying to isolate the problem here!

:D

Ok, here's the exception if I turn cascade="all" on in all the levels:
Code:
java.lang.NullPointerException: attempted to save null
        at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:582)
        at net.sf.hibernate.id.ForeignGenerator.generate(ForeignGenerator.java:35)
        at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:601)
        at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1187)
        at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:77)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:234)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:302)
        at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:741)
        at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:607)
        at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1187)
        at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:77)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:234)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:302)
        at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:741)
        at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:607)
        at XSDMain.doPartyMatter(XSDMain.java:826)
        at XSDMain.saveXML(XSDMain.java:63)
        at XSDMain.xsd(XSDMain.java:1143)
        at XSDMain.xsd(XSDMain.java:1111)
        at Transform.xmlTransform(Transform.java:49)
        at ProcessXML.storeXML(ProcessXML.java:70)
        at ProcessXML.main(ProcessXML.java:99)

Notice how the ForeignGenerator only actually kicks in when it gets to the lowest level.

Anyway. I'll change it to do everything assigned, and get you feedback soon.

-G


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 9:04 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Are you sure you actually fully create the association in both directions? looks like the property is null, instead of pointing to the parent.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 9:10 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
Ok...I seem to hit a little snag with "assigned"...

Code:
12207 [main] ERROR util.JDBCExceptionReporter  - Could not insert
java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]INSERT statement conflicted with COLUMN FOR
EIGN KEY constraint 'FK_Property_XML'. The conflict occurred in database 'CDL', table 'XML', column 'XMLID'.
        at com.microsoft.jdbc.base.BaseExceptions.createException(Unknown Source)
        at com.microsoft.jdbc.base.BaseExceptions.getException(Unknown Source)
        at com.microsoft.jdbc.sqlserver.tds.TDSRequest.processErrorToken(Unknown Source)
        at com.microsoft.jdbc.sqlserver.tds.TDSRequest.processReplyToken(Unknown Source)
        at com.microsoft.jdbc.sqlserver.tds.TDSRPCRequest.processReplyToken(Unknown Source)
        at com.microsoft.jdbc.sqlserver.tds.TDSRequest.processReply(Unknown Source)
        at com.microsoft.jdbc.sqlserver.SQLServerImplStatement.getNextResultType(Unknown Source)
        at com.microsoft.jdbc.base.BaseStatement.commonTransitionToState(Unknown Source)
        at com.microsoft.jdbc.base.BaseStatement.postImplExecute(Unknown Source)
        at com.microsoft.jdbc.base.BasePreparedStatement.postImplExecute(Unknown Source)
        at com.microsoft.jdbc.base.BaseStatement.commonExecute(Unknown Source)
        at com.microsoft.jdbc.base.BaseStatement.executeUpdateInternal(Unknown Source)
        at com.microsoft.jdbc.base.BasePreparedStatement.executeUpdate(Unknown Source)
        at net.sf.hibernate.persister.EntityPersister.insert(EntityPersister.java:472)
        at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:719)
        at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:607)
        at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1187)
        at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:77)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:234)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:268)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:302)
        at net.sf.hibernate.impl.SessionImpl.doUpdate(SessionImpl.java:1285)
        at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1191)
        at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:77)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:234)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:302)
        at net.sf.hibernate.impl.SessionImpl.doUpdate(SessionImpl.java:1285)
        at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1191)
        at net.sf.hibernate.engine.Cascades$4.cascade(Cascades.java:77)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:234)
        at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:302)
        at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:741)
        at net.sf.hibernate.impl.SessionImpl.save(SessionImpl.java:607)
        at XSDMain.doPartyMatter(XSDMain.java:826)
        at XSDMain.saveXML(XSDMain.java:63)
        at XSDMain.xsd(XSDMain.java:1143)
        at XSDMain.xsd(XSDMain.java:1111)
        at Transform.xmlTransform(Transform.java:49)
        at ProcessXML.storeXML(ProcessXML.java:70)

From that trace, it appears to want to save a new XML, then do an Update on Matter (doesn't exist), then an update on Properties (doesn't exist), then save on Property (but the FK reference to Properties cannot be null...)

Any thoughts on that?

-G

PS.
(Just read your post...while I was writing this)
Remember, I still create the links:
Code:
    property.setProperties(props);
    properties.set(i, property);
}
props.setProperty(properties);
matter.setProperties(props);


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 9:13 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
On the "constraint 'FK_Property_XML'", this refers to the DB foreign keys...all tables have XMLID in them...so the FK rules all go from XML to whichever other table....just so you don't think it's a weird rule. :)

-G


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 9:47 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
remember you can't use unsaved-value="null" with assigned ids. You must set unsaved-value="any"


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 10:03 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
gavin wrote:
remember you can't use unsaved-value="null" with assigned ids. You must set unsaved-value="any"

Oops, yeah, sorry, forgot that one. :P

Ok, here are current mappings:
Code:
        <class name="cdl.impl.XMLImpl" table="XML">
            <id name="XMLID" column="XMLID" type ="java.lang.Long" unsaved-value="any">
                <generator class="assigned"/>
            </id>
                <one-to-one name="Matter" class="cdl.impl.MatterImpl" cascade="all"/>

Code:
        <class name="cdl.impl.MatterImpl" table="Matter">
            <id name="XMLID" column="XMLID" type ="java.lang.Long" unsaved-value="any">
                <generator class="assigned">
                    <param name="property">XML</param>
                </generator>
            </id>
            <one-to-one name="Properties" class="cdl.impl.PropertiesImpl" cascade ="all" />
            <one-to-one name="XML" class="cdl.impl.XMLImpl" constrained="true"/>

Code:
    <class name="cdl.impl.PropertiesImpl" table="Properties">
            <id name="XMLID" column="XMLID" type ="java.lang.Long" unsaved-value="any">
                <generator class="assigned">
                    <param name="property">Matter</param>
                </generator>
            </id>
            <one-to-one name="Matter" class="cdl.impl.MatterImpl" constrained="true"/>
        <bag name="Property" inverse="true" lazy="false" cascade="all">
            <key column="XMLID" />
            <one-to-many class="cdl.impl.PropertyImpl" />
        </bag>
    </class>

Code:
    <class name="cdl.impl.PropertyImpl" table="Property">
        <id name="PropertyID" column="PropertyID" type ="java.lang.Long" unsaved-value="null">
            <generator class="identity"/>
        </id>
        <many-to-one name="Properties" class="cdl.impl.PropertiesImpl" column="XMLID" not-null="true" />

With this, it throws an exception:
Code:
java.sql.SQLException: [Microsoft][SQLServer 2000 Driver for JDBC][SQLServer]Cannot insert the value NULL into column 'X
MLID', table 'CDL.dbo.Property'; column does not allow nulls. INSERT fails.


Code:
            Long newID = new Long(100);
            xml.setXMLID(newID);
            xml.getMatter().setXMLID(xml.getXMLID());
            xml.getMatter().getProperties().setXMLID(xml.getXMLID());
            for (int i=0; i < xml.getMatter().getProperties().getProperty().size(); i++) {
                ((Property)xml.getMatter().getProperties().getProperty().get(i)).setXMLID(xml.getXMLID());
// and I've tried this too:
//                 ((Property)xml.getMatter().getProperties().getProperty().get(i)).setProperties(xml.getMatter().getProperties());
// But it throws the same exception
            }
            session.save(xml);

(remember, I DO set the child.setParent()'s elsewhere)

As I said, this is an investigation, because the system works, so if you have other stuff to work on, please don't kill yourself over this. :)

-G


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 10:11 am 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Don't mix "identity" generation strategy with other strategies. It means that the PropertyImpl will get inserted first, before the others (which get inserted at flush time).

Use hilo or something for the PropertyImpl


Top
 Profile  
 
 Post subject:
PostPosted: Fri Nov 14, 2003 10:22 am 
Senior
Senior

Joined: Tue Sep 23, 2003 8:18 am
Posts: 137
Location: Johannesburg, South Africa
gavin wrote:
Don't mix "identity" generation strategy with other strategies. It means that the PropertyImpl will get inserted first, before the others (which get inserted at flush time).

Use hilo or something for the PropertyImpl

Ok, I didn't know that. Something learnt today. :)

I set it to assigned (since I'm only inserting one property for now) and the final cascade worked.

So the mappings are as I posted before, just with the Property generator changed.

We've now established that a full cascade works for multiple 1-1's and a final 1-M, if we don't use Foreign, or Identity, just lots of Assigned.

What now? :)

-G


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 30 posts ]  Go to page 1, 2  Next

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.