-->
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.  [ 2 posts ] 
Author Message
 Post subject: Problem handling of collections with CompositeId ? Please
PostPosted: Tue Mar 27, 2007 8:25 am 
Newbie

Joined: Mon Mar 26, 2007 4:13 pm
Posts: 1
Hello, I have a problem with my collections.

When I want to add an element in my collection, I have the following error:

"could not synchronize database state with sessionNHibernate.StaleStateException: Unexpected row count: 0; expected: 1"


But if I modify an element of the list with the same method SaveOrUpdate () it work very well.

Using version : NHibernate 1.2.0.CR1

My mapping code :
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="A" table="law_info">

    <id name="Id" column="id" type="int">
      <generator class="native"></generator>
    </id>

    <property name="Name" column="description" type="string"></property>
    <property name="DateCreation" column="creationDate" type="datetime"></property>
    <property name="DefaultComponent" column="defaultComponentId" type="int"></property>

   
    <set name="ListComponentSegment" fetch="join" cascade="all-delete-orphan" lazy="true" inverse="false">
      <key column="dcLawId"></key>
      <one-to-many class="B"/>
    </set>

  </class>


  <class name="B" table="law" dynamic-insert="true" dynamic-update="true">
    <composite-id>
      <key-property name="RuleId" column="dcLawId" type="int"></key-property>
      <key-property name="Order" column="lawOrder" type="int"></key-property>
      <key-property name="Segment" column="segmentId" type="int"></key-property>
    </composite-id>
    <property name="RuleId" column="dcLawId" type="int"></property>
    <property name="Order" column="lawOrder" type="int"></property>
    <property name="Segment" column="segmentId" type="int"></property>
    <property name="Component" column="componentId" type="int"></property>
  </class>

</hibernate-mapping>


I think that is due to my multiple key of the class B because if I create a single primary key, it work very well!

Does somebody known a solution by using multiple key (CompositeId) ?

Thx.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 31, 2007 8:22 pm 
Newbie

Joined: Fri Jan 19, 2007 4:13 am
Posts: 6
Location: Germany / Osnabrueck
Its a little late for an answer, but maybe it might help somebody else.

When you add a new row to your collection with composite keys, you assign directly the ids. From this point on, Hibernate thinks that this row already exists in the database, it has already a primary key set. This causes Hibernate to do an UPDATE instead of an INSERT. But an call to UPDATE in the database returns that "0 rows have been updated". Hibernate expects 1 row to beupdated. This causes the error.

Well now to the solution. I don't know if this works for Hibernate, but it worked for NHibernate pretty well.

1. Create an Interceptor that does something like this one:

Code:
        Public Function OnLoad(ByVal entity As Object, ByVal id As Object, ByVal state() As Object, ByVal propertyNames() As String, ByVal types() As NHibernate.Type.IType) As Boolean Implements NHibernate.IInterceptor.OnLoad
            If TypeOf entity Is BaseCompositeIdEO Then
                CType(entity, BaseCompositeIdEO).isSaved = True
            End If
            Return False
        End Function

        Public Function OnSave(ByVal entity As Object, ByVal id As Object, ByVal state() As Object, ByVal propertyNames() As String, ByVal types() As NHibernate.Type.IType) As Boolean Implements NHibernate.IInterceptor.OnSave
            If TypeOf entity Is BaseCompositeIdEO Then
                CType(entity, BaseCompositeIdEO).isSaved = True
            End If
            Return False
        End Function

        Public Function IsUnsaved(ByVal entity As Object) As Object Implements NHibernate.IInterceptor.IsUnsaved
            If TypeOf entity Is BaseCompositeIdEO Then
                Return Not CType(entity, BaseCompositeIdEO).isSaved
            Else
                Return Nothing
            End If
        End Function


then add the following to each EO that has a composite key

Code:
        Private _isSaved As Boolean = False
        Public Overridable Property isSaved() As Boolean
            Get
                Return _isSaved
            End Get
            Set(ByVal value As Boolean)
                _isSaved = value
            End Set
        End Property


This will help Hibernate to find out, if it should be updated or inserted.

Be carefull: I added the code to a BaseCompositeIdEO class, which made it easy for me to find out, if the class supports the functions in the interceptor. If you don't want to put it in a seperate class, define an interface and change the code in the interceptor to check if the current EO supports the interface

Now all you have to do is to register the interceptor to the current session and thats it.

Sorry for not writing Java-Code, but hopefully this is helpfull for you.


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