-->
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.  [ 12 posts ] 
Author Message
 Post subject: Using detached objects
PostPosted: Wed Jan 21, 2004 12:58 pm 
Hello,

I am looking for some documentation about the use of detached objects with Hibernate. The principle is clear to me, I even wrote some XDoclet extensions to generate transfer objects before I found that Hibernate already supports this. However, I am not clear about some of the details and was hoping that someone can tell me before I have to spend several days to try it all out. I did search the mailing list but couldn't find anything but vague references. Here are my questions:

1. How do I control how much of my object graph gets serialized across relationships? I assume that I have to explicitely load lazily loaded collections, but that everything else will be serialized automatically. Is this correct?

2. Upon association with a new session, can Hibernate really figure out even complex object graphs if I set cascade="all"? The reason I ask is that I found this somewhat tricky in my value object implementation.

3. Are detached objects meant by something called 'long-running transactions' in the manual? I couldn't find a definition for this term anywhere in the manual.

I also have suggestion for the Hibernate manual:
The answer to these questions could be nice little chapter in the performance section, especially if this also explains the term 'long-running transactions' and its relationship to optimistic locking.


Top
  
 
 Post subject: Re: Using detached objects
PostPosted: Wed Jan 21, 2004 2:06 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
fljmayer wrote:
1. How do I control how much of my object graph gets serialized across relationships? I assume that I have to explicitely load lazily loaded collections, but that everything else will be serialized automatically. Is this correct?

Every non proxied, non lazy loaded collection will be in the object graph.

fljmayer wrote:
2. Upon association with a new session, can Hibernate really figure out even complex object graphs if I set cascade="all"? The reason I ask is that I found this somewhat tricky in my value object implementation.

Would say yes, any specific pb

fljmayer wrote:
3. Are detached objects meant by something called 'long-running transactions' in the manual? I couldn't find a definition for this term anywhere in the manual.

It's a tx based on several user actions and usually based on several DB tx.
eg: finding a user by criteria and adding a new address is a user tx and a (not so) long-running one

_________________
Emmanuel


Top
 Profile  
 
 Post subject: Re: Using detached objects
PostPosted: Wed Jan 21, 2004 2:38 pm 
Thanks a lot.

fljmayer wrote:
1. How do I control how much of my object graph gets serialized across relationships? I assume that I have to explicitely load lazily loaded collections, but that everything else will be serialized automatically. Is this correct?

emmanuel wrote:
Every non proxied, non lazy loaded collection will be in the object graph.

And what does that mean for lazy loaded collections? Will they be in the object graph if I initialize them somehow? And will they survive being attached to a new session?

fljmayer wrote:
2. Upon association with a new session, can Hibernate really figure out even complex object graphs if I set cascade="all"? The reason I ask is that I found this somewhat tricky in my value object implementation.

emmanuel wrote:
Would say yes, any specific pb

Difficulties only in my current approach with XDoclet-generated value objects, so I want to avoid further difficulties. Just found out the use of detached objects yesterday but the documentation is a bit spotty.

fljmayer wrote:
3. Are detached objects meant by something called 'long-running transactions' in the manual? I couldn't find a definition for this term anywhere in the manual.

emmanuel wrote:
It's a tx based on several user actions and usually based on several DB tx.
eg: finding a user by criteria and adding a new address is a user tx and a (not so) long-running one

So instead of using multiple sessions and detached objects I could also commit multiple times on the same session?


Top
  
 
 Post subject: Re: Using detached objects
PostPosted: Wed Jan 21, 2004 5:03 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
fljmayer wrote:
And what does that mean for lazy loaded collections? Will they be in the object graph if I initialize them somehow? And will they survive being attached to a new session?

Yes, uninitialized collections, are an Hibernate home-made implementation of Collection that keep a link to the session loading it. So when accessing it for real, the collection will be initialized using the session and become an (almost) usual collection.
Adding, removing elements will be considered as an update when reattaching it.

fljmayer wrote:
the documentation is a bit spotty.

Just play with it (best doc in the world)

fljmayer wrote:
So instead of using multiple sessions and detached objects I could also commit multiple times on the same session?

Yes, instead of closing session (and losing lazy capabilities), you disconnect it (ie close SQL connection) and reconnect it (ie reopening connection), and keep all the session cache scope.
This is particulary useful in a client-server architecture.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 21, 2004 5:51 pm 
Well, thanks again, this was really helpful. One more question:

If I use the long transactions and disconnect the session, can I also serialize my objects and send them over the network to the client, get them back, reconnect the session and work with the deserialized objects within the same old session? I would expect not because the deserialized objects are different instances, so I have to use session.update() to bring them back in. Is this correct?


Top
  
 
 Post subject:
PostPosted: Wed Jan 21, 2004 6:10 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Yes, you have to use session.update() AND evict old objects because Hibernate only allow 1 attached instance per id for a given persisted class.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 21, 2004 7:01 pm 
Currently I create a new Session for every remote call because JBoss took away my JDBC connection anyway when the remote call returned. Do I still have to evict in this case? I guess I could also just disconnect and reconnect my session, but right now I don't see any benefit in that.


Top
  
 
 Post subject:
PostPosted: Thu Jan 22, 2004 4:55 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
No, Think of that
- closing a session will basically detroy it, thus there is no object in cache. When using a new session, the session cache is clean!
- disconnecting a session, will disconnect session from it's SQL connection, but the session cache still remains (and objects have to be evicted if needed). When reconnecting, an SQL connection is attached.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 22, 2004 6:30 pm 
Now I have hit a problem I don't know how to handle. I am getting the folliwng exception:
net.sf.hibernate.PropertyValueException: not-null property references a null or transient value: com.ichg.capsela.domain.component.flow.ControlEdge.sinkVertex

The thing is that this property actually does have a valid value, but the referenced object has not been saved. Let me give you some background information:
I have a class Flow that contains a collection of Vertex objects. One Vertex can be connected to another one through an Edge, so the Edge has a sourceVertex and a sinkVertex. A Vertex has a collection of Edges. In the above example I called Session.update() on a previously save Flow, but the 2 Vertexes and the one Edge are new. When the exception was thrown, the source Vertex and the Edge had already been assigned a primary key, but the sink Vertex still had its unsaved-value as primary key. All collections have cascade="all" and lazy="true".

Is there anything I can do short of adding only Vertexes first?


Top
  
 
 Post subject:
PostPosted: Thu Jan 22, 2004 7:00 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
wo mapping and code it's hard to help

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 23, 2004 11:47 am 
Well, it is a bit of code and I don't want to ask to much of you, but here it is.
Anyway, from my own work with value objects I assume that Hibernate has a problem with more complex object graphs. I resorted to handcoding where necessary.

package com.ichg.capsela.framework;

import java.io.Serializable;

import net.sf.hibernate.Validatable;

/**
* @author Felix L J Mayer
* @version $Revision: 1.9 $
* @created Dec 18, 2003
*/
public abstract class DomainObject implements Validatable, Serializable {

public DomainObject() {
_id = -1;
}//DomainObject()

/**
* @see java.lang.Object#toString()
*/
public String toString() {
return "id=" + _id;
}//toString()

/**
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals( Object object ) {
if( object == null ) return false;
if( object == this ) return true;
if( object.getClass() != getClass() ) return false;
if( ((DomainObject) object).getId() == getId() ) return true;
return false;
}//equals()

/**
* When overriding this method, make sure to call super.update()!
* @throws CapselaException
*/
public void update() throws CapselaException {
Persistence.update( this );
}//update()

// TODO Use primary key class instead of id for domain object?
protected long _id;
/**
* Gets the DomainObject's primary key.
* @return the DomainObject's primary key
* @ejb.value-object setter="false"
*/
public long getId() {
return _id;
}//getId()
/**
* Sets the DomainObject's primary key.
* @param id the DomainObject's primary key
*/
protected void setId( long id ) {
_id = id;
}//setId()

}//DomainObject


package com.ichg.capsela.framework;

/**
* @author Felix L J Mayer
* @version $Revision: 1.8 $
* @created Dec 18, 2003
*/
public abstract class IndependentDomainObject extends DomainObject {

public IndependentDomainObject() {
}//IndependentDomainObject()

public String toString() {
return super.toString() + " version=" + _version;
}//toString()

/**
* Is called in order to initialize any lazy loaded collections before
* the domain object is serialized and sent to the client.
* @throws CapselaException
*/
public void initializeCollections() throws CapselaException {
}//initializeCollections()


private int _version;
/**
* @return the version used for optimistic locking in long transactions
* @ejb.value-object setter="false"
*/
public int getVersion() {
return _version;
}//getVersion()
/**
* @param version the version used for optimistic locking in long transactions
*/
protected void setVersion( int version ) {
_version = version;
}//setVersion()

}//IndependentDomainObject


package com.ichg.capsela.domain.component;

import net.sf.hibernate.ValidationFailure;

import com.ichg.capsela.framework.CapselaException;
import com.ichg.capsela.framework.IndependentDomainObject;

/**
* @author Felix L J Mayer
* @version $Revision: 1.8 $
* @created Dec 5, 2003
*
* @hibernate.class table="COMPONENT" discriminator-value="0" dynamic-update="true"
* @hibernate.discriminator column="COMPONENT_TYPE" type="integer"
*/
public abstract class Component extends IndependentDomainObject {

public Component() {
}//Component()

/**
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + " type=" + _type + " name=" + _name
+ " folderID=" + _folderID;
}//toString()

/**
* @see net.sf.hibernate.Validatable#validate()
*/
public void validate() throws ValidationFailure {
if( _name == null ) throw new ValidationFailure("_name == null");
if( _folder == null ) throw new ValidationFailure("_folder == null");
if( _folder.equals( this ) ) throw new ValidationFailure("_folder.equals( this )");
}//validate()

public abstract void run() throws CapselaException;

/**
* Gets the Component's primary key.
* This method is only needed for the Hibernate mapping.
* @return the component's primary key
* @hibernate.id column="COMPONENT_ID" type="long" generator-class="native"
* unsaved-value="-1"
*/
public long getId() {
return super.getId();
}//getId()

/**
* @return the version used for optimistic locking in long transactions
* This method is only needed for the Hibernate mapping.
* @hibernate.version column="COMPONENT_VERSION" type="integer"
*/
public int getVersion() {
return super.getVersion();
}//getVersion()


private int _type;
/**
* @return
* @hibernate.property column="COMPONENT_TYPE" insert="false" update="false"
*/
public int getType() {
return _type;
}//getType()

protected void setType( int type ) {
_type = type;
}//setType()


private String _name;
/**
* Gets the component's name.
* @return the Component's name
* @hibernate.property column="COMPONENT_NAME" length="50" not-null="true" unique="true"
*/
public String getName() {
return _name;
}//getName()
/**
* Sets the component's name.
* @param name the component's name
*/
public void setName( String name ) {
assert name != null : "name != null";
_name = name;
}//setName()


private FolderComponent _folder;
/**
* @return
* @hibernate.many-to-one column="FOLDER_COMPONENT_ID"
* class="com.ichg.capsela.domain.component.FolderComponent"
*/
public FolderComponent getFolder() {
return _folder;
}//getFolder()
public void setFolder( FolderComponent folder ) {
assert folder != null : "folder != null";
_folder = folder;
}//setFolder()

private long _folderID;
/**
* @return
* @hibernate.property column="FOLDER_COMPONENT_ID" insert="false" update="false"
*/
public long getFolderID() {
return _folderID;
}//getFolderID()
protected void setFolderID( long folderID ) {
_folderID = folderID;
}//setFolderID()

}//Component


package com.ichg.capsela.domain.component;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import com.ichg.capsela.domain.component.flow.ComponentVertex;
import com.ichg.capsela.domain.component.flow.FlowVertex;
import com.ichg.capsela.domain.component.flow.LayerVertex;
import com.ichg.capsela.framework.CapselaException;
import com.ichg.capsela.framework.Persistence;

/**
* @author Felix L J Mayer
* @version $Revision: 1.7 $
* @created Dec 16, 2003
*
* @hibernate.subclass discriminator-value="4"
*/
public class FlowComponent extends FolderComponent {

public FlowComponent() {
}//FlowComponent()

/**
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + " selectedLayerIndex=" + _selectedLayerIndex
+ " layerIdentifiers=" + _layerIdentifiers
+ " visibilityLevel=" + _visibilityLevel;
}//toString()

/**
* @see com.ichg.capsela.framework.DomainObject#update()
*/
public void update() throws CapselaException {
Persistence.update( this );
for( Iterator i = getVertices().iterator(); i.hasNext(); ) {
}//for
}//update()

public void run() {
}//run()


private Set _vertices = new HashSet();
/**
* @return
* @hibernate.set role="vertices" cascade="all"
* @hibernate.collection-key column="WORKFLOW_COMPONENT_ID"
* @hibernate.collection-one-to-many
* class="com.ichg.capsela.domain.component.flow.FlowVertex"
*/
public Set getVertices() {
return _vertices;
}//getVertices()

public void setVertices( Set vertices ) {
assert vertices != null : "vertices != null";
_vertices = vertices;
}//setVertices()

public void addVertex( FlowVertex vertex ) {
assert vertex != null : "vertex != null";
assert ! _vertices.contains( vertex ) : "! _vertices.contains( vertex )";
_vertices.add( vertex );
vertex.setFlow( this );
}//addVertex()

public void removeVertex( FlowVertex vertex ) {
assert vertex != null : "vertex != null";
assert _vertices.contains( vertex ) : "_vertices.contains( vertex )";
_vertices.remove( vertex );
// TODO This means that the vertex needs to be deleted.
}//addVertex()

public Set getFlowVertices() {
Set flowVertices = new HashSet();
for( Iterator iter = getVertices().iterator(); iter.hasNext(); ) {
FlowVertex vertex = (FlowVertex) iter.next();
if( vertex instanceof ComponentVertex ) {
flowVertices.add( vertex );
}//if
}//for
return flowVertices;
}//getLayerVertices()

public Set getReferencingLayerVertices() {
Set layerVertices = new HashSet();
for( Iterator iter = getVertices().iterator(); iter.hasNext(); ) {
FlowVertex vertex = (FlowVertex) iter.next();
if( vertex instanceof LayerVertex ) {
layerVertices.add( vertex );
}//if
}//for
return layerVertices;
}//getLayerVertices()


private int _selectedLayerIndex = 0;
/**
* @return The selectedLayerIndex value
* @hibernate.property column="SELECTED_LAYER_INDEX"
*/
public int getSelectedLayerIndex() {
return _selectedLayerIndex;
}//getSelectedLayerIndex()
/**
* @param selectedLayerIndex The new selectedLayerIndex value
*/
public void setSelectedLayerIndex( int selectedLayerIndex ) {
this._selectedLayerIndex = selectedLayerIndex;
}//setSelectedLayerIndex()


private Vector _layerIdentifiers = null;
/**
* @return The layerIdentifiers value
* @hibernate.property column="LAYER_IDENTIFIERS" length="65535"
*/
public Vector getLayerIdentifiers() {
return _layerIdentifiers;
}//getLayerIdentifiers()
/**
* @param layerIdentifiers The new layerIdentifiers value
*/
public void setLayerIdentifiers( Vector layerIdentifiers ) {
this._layerIdentifiers = layerIdentifiers;
}//setLayerIdentifiers()


private int _visibilityLevel = 0;
/**
* @return The visibilityLevel value
* @hibernate.property column="VISIBILITY_LEVEL"
*/
public int getVisibilityLevel() {
return _visibilityLevel;
}//getVisibilityLevel()
/**
* @param visibilityLevel The new visibilityLevel value
*/
public void setVisibilityLevel( int visibilityLevel ) {
this._visibilityLevel = visibilityLevel;
}//setVisibilityLevel()


}//FlowComponent


package com.ichg.capsela.domain.component.flow;

import net.sf.hibernate.ValidationFailure;

import com.ichg.capsela.domain.component.Component;
import com.ichg.capsela.domain.component.FlowComponent;
import com.ichg.capsela.framework.Helper;
import com.ichg.capsela.framework.IndependentDomainObject;

/**
* @author Felix L J Mayer
* @version $Revision: 1.10 $
* @created Dec 5, 2003
*
* @hibernate.class table="FLOW_VERTEX" discriminator-value="C"
* @hibernate.discriminator column="VERTEX_TYPE" type="character"
*/
public abstract class FlowVertex extends IndependentDomainObject {

public FlowVertex() {
}//FlowVertex

/**
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + " flow=" + Helper.id( _flow )
+ " referencedComponent=" + Helper.id( _referencedComponent );
}//toString()

/**
* @see net.sf.hibernate.Validatable#validate()
*/
public void validate() throws ValidationFailure {
if( _flow == null ) throw new ValidationFailure("_workflow == null");
if( _referencedComponent == null ) throw new ValidationFailure("_referencedComponent == null");
if( _flow == _referencedComponent ) throw new ValidationFailure("_workflow == _referencedComponent");
}//validate()

/**
* The get method for primary key
* @return The id value
* @hibernate.id column="FLOW_VERTEX_ID" type="long" generator-class="native"
* unsaved-value="-1"
*/
public long getId() {
return super.getId();
}//getId()


private FlowComponent _flow;
/**
* @return
* @hibernate.many-to-one column="FLOW_COMPONENT_ID" not-null="true"
* class="com.ichg.capsela.domain.component.FlowComponent"
* ejb.value-object
*/
public FlowComponent getFlow() {
return _flow;
}//getFlow()

public void setFlow( FlowComponent workflow ) {
assert workflow != null : "workflow != null";
_flow = workflow;
}//setFlow()

private long _flowID;
/**
* @return
* @hibernate.property column="FLOW_COMPONENT_ID" insert="false" update="false"
*/
public long getFlowID() {
return _flowID;
}//getFlowID()
protected void setFlowID( long flowID ) {
_flowID = flowID;
}//setFlowID()


private Component _referencedComponent;
/**
* @return
* @hibernate.many-to-one column="REFERENCED_COMPONENT_ID" not-null="true"
* class="com.ichg.capsela.domain.component.Component"
* @ejb.value-object
* aggregate="com.ichg.capsela.domain.component.ComponentVO"
* aggregate-name="ReferencedComponent"
* members="com.ichg.capsela.domain.component.Component"
* members-name="ValueObject" relation="external"
*/
public Component getReferencedComponent() {
return _referencedComponent;
}//getReferencedComponent()

public void setReferencedComponent( Component component ) {
assert component != null : "component != null";
_referencedComponent = component;
}//setReferencedComponent()

private long _referencedComponentID;
/**
* @return
* @hibernate.property column="REFERENCED_COMPONENT_ID" insert="false" update="false"
*/
public long getReferencedComponentID() {
return _referencedComponentID;
}//getReferencedComponentID()
protected void setReferencedComponentID( long referencedComponentID ) {
_referencedComponentID = referencedComponentID;
}//setReferencedComponentID()

}//FlowVertex


package com.ichg.capsela.domain.component.flow;

import java.awt.Rectangle;
import java.util.HashSet;
import java.util.Set;

/**
* @author Felix L J Mayer
* @version $Revision: 1.7 $
* @created Dec 16, 2003
*
* @hibernate.subclass discriminator-value="W"
*/
public class ComponentVertex extends FlowVertex {

public ComponentVertex() {
_sourceEdges = new HashSet();
_sinkEdges = new HashSet();
}//ComponentVertex()

/**
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + " sourceEdges.size()=" + _sourceEdges.size()
+ " sinkEdges.size()=" + _sinkEdges.size()
+ " guiLocation=" + _guiLocation;
}//toString()


private Set _sourceEdges;
/**
* @return
* @hibernate.set role="sourceEdges" cascade="all" lazy="true"
* @hibernate.collection-key column="SOURCE_VERTEX_ID"
* @hibernate.collection-one-to-many
* class="com.ichg.capsela.domain.component.flow.FlowEdge"
*/
public Set getSourceEdges() {
return _sourceEdges;
}//getSourceEdges()

public void setSourceEdges( Set edges ) {
assert edges != null : "edges != null";
_sourceEdges = edges;
}//setSourceEdges()

public void addSourceEdge( FlowEdge edge ) {
assert edge != null : "edge != null";
assert ! _sourceEdges.contains( edge ) : "! _sourceEdges.contains( edge )";
_sourceEdges.add( edge );
edge.setSourceVertex( this );
}//addSourceEdge()

public void removeSourceEdge( FlowEdge edge ) {
assert edge != null : "edge != null";
assert _sourceEdges.contains( edge ) : "_sourceEdges.contains( edge )";
_sourceEdges.remove( edge );
}//addSourceEdge()

public boolean isSourceEdge( FlowEdge edge ) {
return _sourceEdges.contains( edge );
}//isSourceEdge()


private Set _sinkEdges;
/**
* @return
* @hibernate.set role="sinkEdge" cascade="all" lazy="true"
* @hibernate.collection-key column="SINK_VERTEX_ID"
* @hibernate.collection-one-to-many
* class="com.ichg.capsela.domain.component.flow.FlowEdge"
*
* @ejb.value-object compose="FlowEdgeVO" compose-name="SinkEdge"
* members="FlowEdge" members-name="ValueObject"
* relation="external" type="Set" parent="true"
*/
public Set getSinkEdges() {
return _sinkEdges;
}//getSinkEdges()

public void setSinkEdges( Set edges ) {
assert edges != null : "edges != null";
_sinkEdges = edges;
}//setSinkEdges()

public void addSinkEdge( FlowEdge edge ) {
assert edge != null : "edge != null";
assert ! _sinkEdges.contains( edge ) : "! _sinkEdge.contains( edge )";
_sinkEdges.add( edge );
edge.setSinkVertex( this );
}//addSinkEdge()

public void removeSinkEdge( FlowEdge edge ) {
assert edge != null : "edge != null";
assert _sinkEdges.contains( edge ) : "_sinkEdge.contains( edge )";
_sinkEdges.remove( edge );
// TODO This means that the edge needs to be deleted.
}//addSinkEdge()

public boolean isSinkEdge( FlowEdge edge ) {
return _sinkEdges.contains( edge );
}//isSourceEdge()


private Rectangle _guiLocation;
/**
* The get method for location of the node in the gui
*
* @return The guiLocation value
* @hibernate.property column="GUI_LOCATION"
* @ejb.value-object
*/
public Rectangle getGuiLocation() {
return _guiLocation;
}//getGuiLocation()
/**
* The setter method for the location of the node in the gui
*
* @param guiLocation The new guiLocation value
*/
public void setGuiLocation( Rectangle guiLocation ) {
_guiLocation = guiLocation;
}//setGuiLocation(


}//ComponentVertex


package com.ichg.capsela.domain.component.flow;

import net.sf.hibernate.ValidationFailure;

import com.ichg.capsela.framework.Helper;
import com.ichg.capsela.framework.IndependentDomainObject;

/**
* @author Felix L J Mayer
* @version $Revision: 1.8 $
* @created Dec 16, 2003
*
* @hibernate.class table="FLOW_EDGE" discriminator-value="E"
* @hibernate.discriminator column="EDGE_TYPE"
*/
public abstract class FlowEdge extends IndependentDomainObject {

public FlowEdge() {
}//FlowEdge()

/**
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString()
+ " sourceVertex=" + Helper.id( _sourceVertex )
+ " sinkVertex=" + Helper.id( _sinkVertex );
}//toString()

/**
* @see net.sf.hibernate.Validatable#validate()
*/
public void validate() throws ValidationFailure {
// Some of these are covered by the database constraints and Hibernate.
if( _sourceVertex == null ) throw new ValidationFailure("_sourceVertex == null");
if( _sinkVertex == null ) throw new ValidationFailure("_sinkVertex == null");
if( _sourceVertex.equals( _sinkVertex ) ) throw new ValidationFailure("_sourceVertex.equals( _sinkVertex )");
}//validate()


/**
* Gets the FlowEdge's primary key.
* This method is only needed for the hibernate mapping.
* @return The id value
* @hibernate.id column="FLOW_EDGE_ID" type="long" generator-class="native"
* unsaved-value="-1"
*/
public long getId() {
return super.getId();
}//getId()


private ComponentVertex _sourceVertex;
/**
* @return
* @hibernate.many-to-one column="SOURCE_VERTEX_ID" not-null="true"
* class="com.ichg.capsela.domain.component.flow.ComponentVertex"
*/
public ComponentVertex getSourceVertex() {
return _sourceVertex;
}//getSourceVertex()
public void setSourceVertex( ComponentVertex vertex ) {
assert vertex != null : "vertex != null";
assert _sinkVertex == null || _sinkVertex.getReferencedComponent().equals( vertex.getReferencedComponent() )
: "_sinkVertex == null || _sinkVertex.getComponent().equals( vertex.getComponent() )";
_sourceVertex = vertex;
}//setSourceVertex()

private long _sourceVertexID;
/**
* @return
* @hibernate.property column="SOURCE_VERTEX_ID" insert="false" update="false"
*/
public long getSourceVertexID() {
return _sourceVertexID;
}//getSourceVertexID()
protected void setSourceVertexID( long sourceVertexID ) {
_sourceVertexID = sourceVertexID;
}//setSourceVertexID()


private ComponentVertex _sinkVertex;
/**
* @return
* @hibernate.many-to-one column="SINK_VERTEX_ID" not-null="true"
* class="com.ichg.capsela.domain.component.flow.ComponentVertex"
*/
public ComponentVertex getSinkVertex() {
return _sinkVertex;
}//getSinkVertex()
public void setSinkVertex( ComponentVertex vertex ) {
assert vertex != null : "vertex != null";
assert _sourceVertex == null || _sourceVertex.getReferencedComponent().equals( vertex.getReferencedComponent() )
: "_sourceVertex == null || _sourceVertex.getComponent().equals( vertex.getComponent() )";
_sinkVertex = vertex;
}//setSinkVertex()

private long _sinkVertexID;
/**
* @return
* @hibernate.property column="SINK_VERTEX_ID" insert="false" update="false"
*/
public long getSinkVertexID() {
return _sinkVertexID;
}//getSinkVertexID()
protected void setSinkVertexID( long sinkVertexID ) {
_sinkVertexID = sinkVertexID;
}//setSinkVertexID()


}//FlowEdge


package com.ichg.capsela.domain.component.flow;

/**
* @author Felix L J Mayer
* @version $Revision: 1.5 $
* @created Dec 16, 2003
*
* @hibernate.subclass table="EDGE" discriminator-value="C"
*/
public class ControlEdge extends FlowEdge {

public ControlEdge() {
}//ControlEdge()

/**
* @see java.lang.Object#toString()
*/
public String toString() {
return super.toString() + " name=" + _name;
}//toString()

public String _name;
/**
* Gets the name attribute of the ControlEdge object
*
* @return The name value
* @hibernate.property column="EDGE_NAME"
*/
public String getName() {
return _name;
}//getName()

public void setName( String name ) {
_name = name;
}//setName()

}//ControlEdge


Top
  
 
 Post subject:
PostPosted: Fri Jan 23, 2004 1:21 pm 
I got it to work by setting cascasde="none" and doing a saveOrUpdate() myself. But I do think that Hibernate has a weakness in managing cascades. I don't think that this comes from any bad coding, but from the inherent complexity of the matter: There are many ways to traverse a graph, and a fixed traversal algorithm will always hit some uninitialized objects, which causes validation to fail. I could imagine that an algorithm which detects such cases and then proceeds somewhere else might be more successful because it would then have another chance to get the uninitialized objects.


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