-->
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.  [ 3 posts ] 
Author Message
 Post subject: Simple Collection Mapping Question
PostPosted: Fri Jul 06, 2007 7:48 am 
Beginner
Beginner

Joined: Sat Dec 16, 2006 1:52 pm
Posts: 40
I have a collection mapping. Recently I tried to make the key not-null because in the database I want both the foreign keys on this table to be not null. But when I try to save an object that would put data into this table I get an exception about having a null value. But nothing should be null. I'm using hibernate 3.2.0 due to bugs in more recent versions.

The key in question is the key column S_ComponentInstanceID, and the column T_ComponentInstanceID.

Note: I just made it null in the metadata, I have not regenerated the db yet to get the not-null constraing put onto the actual db. But this exception is on hibernate level not jdbc driver.

This could be a bug as I have the same type of mapping using a list and it works. But this mapping is set not list, and the object in question must be in two separate sets. And its failing.



This is the class file.
Code:
public final class DBComponentInstance extends DBContainableGraphic implements IDSComponentInstance {
   private static final long serialVersionUID = 1L;

   private DBContainerGraphic container;
   
       //only used as identifer. no methods on component are ever called from this reference!!
    private Long component;

    /*
     * Note, a sourced connection connects its source here.(source to source)
     *
     * 1-N uni-directional Set with foreign key.  It means the component
     * instance table will not have any entry but a foreign key will be used in
     * the connections table.
     * uni-directional means the component instance class has a reference to
     * the connections class, but the connections class does not have a
     * reference to the component instance class.
     *
     */
    private Set<DBFunctionConnection> sourceConnections;
    private Set<DBFunctionConnection> targetConnections;
   
    public DBComponentInstance(Point location, Dimension size) {
      super(location,size);
        this.container = new DBContainerGraphic();
        this.sourceConnections = new HashSet<DBFunctionConnection>();
        this.targetConnections = new HashSet<DBFunctionConnection>();
   }
    /*
     * We do not want proxy for graphical objects.  So we dont need package
     * scope here.
     */
    private DBComponentInstance(){
    }
}

and this
Code:
public final class DBFunctionConnection implements IDSFunctionConnection, Serializable, Cloneable{
   private static final long serialVersionUID = 1L;
   /*
     * Hibernate spec version 3.2.0.ga section 4.1.2 states that transitive
     * reattachment of detached objects requires an identifier.  So we have one.
     */
    private Long id; // identifier
    private List<DBBendpointGraphics> bendPoints = new ArrayList<DBBendpointGraphics>();
    private int sourceLocationX,sourceLocationY;
    private int targetLocationX,targetLocationY;
    //private DBCircuit circuit;
    private Long circuit;
   
    public DBFunctionConnection(Point sourceLocation, Point targetLocation) {
        super();
        assert sourceLocation != null;
        assert targetLocation != null;
        this.sourceLocationX = sourceLocation.x;
        this.sourceLocationY = sourceLocation.y;
        this.targetLocationX = targetLocation.x;
        this.targetLocationY = targetLocation.y;
    }
    /*
     * We do not want proxy for graphical objects.  So we dont need package
     * scope here.
     */
    private DBFunctionConnection(){
    }
}



The metadata is as follows
Code:
<hibernate-mapping>
  <class name="com.rgdsft.hib.core.DBFunctionConnection" table="dbfunctionconnection" lazy="false">
    <id name="id" type="long">
       <generator class="native"/>
   </id>
    <property name="sourceLocationX" not-null="true" access="field"/>
    <property name="sourceLocationY" not-null="true" access="field"/>
    <property name="targetLocationX" not-null="true" access="field"/>
    <property name="targetLocationY" not-null="true" access="field"/>
   
    <property name="circuit" column="circuitid" access="field" type="long"/>
   
   <list name="bendPoints" access="field" lazy="false" cascade="all-delete-orphan">
      <key column="FunctionConnectionID" not-null="true"/>
      <list-index column="sortOrder"/>
      <one-to-many class="com.rgdsft.hib.core.DBBendpointGraphics" />
   </list>
       
  </class>
</hibernate-mapping>
<hibernate-mapping>
  <joined-subclass name="com.rgdsft.hib.core.DBComponentInstance" extends="com.rgdsft.hib.core.DBContainableGraphic" table="dbcomponentinstance" lazy="false">
    <key column="OBJECT_ID"/> 

    <property name="component" column="componentid" access="field" type="long"/>
       
    <many-to-one name="container" column="ContainerID" not-null="true" unique="true" access="field" cascade="all" lazy="false"/>
   
    <set name="sourceConnections" access="field" lazy="false" cascade="all,delete-orphan">
      <!-- key column is not null since connectons must always have both ends when saved -->   
      <key column="S_ComponentInstanceID" not-null="true"/>
      <one-to-many class="com.rgdsft.hib.core.DBFunctionConnection"/>
    </set>

    <!-- cascade is all,delete-orphan.  Connection life is totally dependent on
    the component instance. Plus, conns are removed from comp instance prior to
    deletion, so delete-orphan is required else hibernate will attempt to remove
    comp instances from conn which will cause constraint exception due to the
    not-null constraing on the comp instance id -->
    <set name="targetConnections" access="field" lazy="false" cascade="all,delete-orphan">
      <!-- key column is not null since connectons must always have both ends when saved -->
      <key column="T_ComponentInstanceID" not-null="true"/>
      <one-to-many class="com.rgdsft.hib.core.DBFunctionConnection"/>
    </set>
       
  </joined-subclass>
</hibernate-mapping>



I am getting this exception
Quote:
org.hibernate.PropertyValueException: not-null property references a null or transient value: com.rgdsft.hib.core.DBFunctionConnection._targetConnectionsBackref
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:284)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:98)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.engine.Cascade.cascade(Cascade.java:97)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:332)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:304)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:217)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.engine.Cascade.cascade(Cascade.java:97)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:332)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:304)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:217)
at org.hibernate.event.def.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:564)
at org.hibernate.impl.SessionImpl.update(SessionImpl.java:552)
at org.hibernate.impl.SessionImpl.update(SessionImpl.java:544)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 06, 2007 10:39 am 
Beginner
Beginner

Joined: Sat Dec 16, 2006 1:52 pm
Posts: 40
I guess this is a hibernate bug or an unimplemented feature. The problem appears to be that hibernate does not handle the contained element being a member of two collections and having cascade from both collections. So all I had to do was remove all cascading from the one collection. It works since the not-null will ensure database integrity, and since both ends are not-null, it is sufficient to do cascade-delete from just one end.

The new Mapping is this
Code:
<hibernate-mapping>
  <joined-subclass name="com.rgdsft.hib.core.DBComponentInstance" extends="com.rgdsft.hib.core.DBContainableGraphic" table="dbcomponentinstance" lazy="false">
    <key column="OBJECT_ID"/> 

    <!-- this is for non-DDL only -->
    <property name="component" column="componentid" access="field" type="long"/>
       
    <many-to-one name="container" column="ContainerID" not-null="true" unique="true" access="field" cascade="all" lazy="false"/>
   
    <!-- cascade is all,delete-orphan.  Connection life is totally dependent on
    the component instance. Plus, conns are removed from comp instance prior to
    deletion, so delete-orphan is required else hibernate will attempt to remove
    comp instances from conn which will cause constraint exception due to the
    not-null constraing on the comp instance id -->   
    <set name="sourceConnections" access="field" lazy="false" cascade="all-delete-orphan">
      <!-- key column is not null since connectons must always have a source end when saved -->   
      <key column="S_ComponentInstanceID" not-null="true"/>
      <one-to-many class="com.rgdsft.hib.core.DBFunctionConnection"/>
    </set>

    <!-- cascade is none.  Hibernate has a problem cascading on save when both
    ends of the connection are not-null.  I get a not-null constraint violation.
    So my solution is to not cascade anything from the target side.  The
    not-null constraint will ensure database integrity.  And all actions will
    occur inspired from the source side. -->
    <set name="targetConnections" access="field" lazy="false">
      <!-- key column is not null since connectons must always have a target end when saved -->
      <key column="T_ComponentInstanceID" not-null="true"/>
      <one-to-many class="com.rgdsft.hib.core.DBFunctionConnection"/>
    </set>
       
  </joined-subclass>


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jul 06, 2007 10:57 am 
Beginner
Beginner

Joined: Sat Dec 16, 2006 1:52 pm
Posts: 40
Bah, that did not last long. I think what happens is the DBComponentInstance gets saved, then the save cascades to the DBFunctionConnection, but the DBFunctionConnection belongs to two seperate DBComponentInstances.

So we have this

DBComponentInstance(A) --- DBFunctionConnection --- DBCOmponentInstance(B)

if A starts the save, it cascades to DBFunctionConnection, but B has not been saved yet and I get a constraint violation. Hibernate needs to recognize the DBComponentInstance(B) is in the session and ready to be saved and save it. Until that time, I will have to drop the not-null constraint I guess :(


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