-->
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.  [ 8 posts ] 
Author Message
 Post subject: Deleting dataobjects not physically, marking only with flag
PostPosted: Wed Feb 15, 2006 5:35 am 
Newbie

Joined: Mon Jan 30, 2006 9:15 am
Posts: 11
Hello,

we want to implement a relative big project (120 Data Objects) with nhibernate, the general functionality of nhibernate is clear ...

But a view thinks are a "bit cloudy":

We don't want to delete the data objects physicaly, it should only be set an object state:

General Table design:
table [xy]
pk -- guid, or autovalue of bigint
ostate int -- 0 default, 1 .. deleted

This means if i access a deleted data object (ostate==1) it should not be returned (return null)

Simplified example for a one to one relation:

Code:
   [Serializable]
   public class DataObject : IDataObject
   {
      private long _id;
      public long Id
      {
         get { return _id; }
         set { _id = value; }
      }

      private int _oState;
      public int OState
      {
         get { return _oState; }
         set { _oState = value; }
      }
      public override bool Equals(object obj)
      {
         Key key = obj as Key;
         if (key != null && key._id == this._id && key.OState == this._oState)
            return true;
         return false;
      }
      public override int GetHashCode()
      {
         return _id.GetHashCode() ^ _oState.GetHashCode();
      }
   }
   [Serializable]
   public class DoWfObject : DataObject
   {

      private DoWfObjectData _data;

      public DoWfObjectData Data
      {
         get { return _data; }
         set { _data = value; }
      }

      public DoWfObject()
      {
      }
   }

   [Serializable]
   public class DoWfObjectData : DataObject
   {
      private DoWfObject obj;

      public DoWfObject Object
      {
         get { return _object; }
         set { _object = value; }
      }

      public DoWfObjectData()
      {
      }
   }


This means in the following scenario:
DoWfObject (ostate default)
DoWfObjectData (ostate deleted)

wfObject.Data should return null

I have tried it with several different meachnisms:

where attribute:
<class name="DoWfObject" table="WfObject" where="OState=0">
This constraint is only used for HQLs (in some cases), not for loading an object graph like DoWfObject.Data.


Composite-Id:
Code:
      <composite-id>
         <key-property name="Id" column="idWfObject" type="Int64" access="nosetter.camelcase-underscore"/>
         <key-property name="OState" column="OState" type="Int32" access="nosetter.camelcase-underscore"/>
      </composite-id>
...
      <many-to-one insert="false" update="false" name="Object" not-null="true" class="DoWfObject" unique="true">
         <column name="idObject"/>
         <column name="'0'" />
      </many-to-one>

This returns me some errors (i can provide you additional infos, if neccessary)

But i'm generally not sure if this is the right way.

Can anyone tell me if it is possible to implement such a mechanism with the current Nhibernate 1.0.2.0 version


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 7:40 am 
Regular
Regular

Joined: Fri Jun 11, 2004 6:27 am
Posts: 81
Location: Yaroslavl, Russia
In general, you can solve it using database-only approach:
1. Create views for all tables, which must behave in this way. View must select only records that are not marked as "deleted".
2. Create an INSTEAD OF DELETE triggers on those views, that will not delete record, but mark it as deleted instead.
3. Map your persistent objects to views instead of tables.

This is based on MS SQL functionality, but other "correct" DBMSs have analogues. :)

_________________
Best,
Andrew Mayorov // BYTE-force


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 8:49 am 
Newbie

Joined: Mon Jan 30, 2006 9:15 am
Posts: 11
xor wrote:
In general, you can solve it using database-only approach:
1. Create views for all tables, which must behave in this way. View must select only records that are not marked as "deleted".
2. Create an INSTEAD OF DELETE triggers on those views, that will not delete record, but mark it as deleted instead.
3. Map your persistent objects to views instead of tables.

This is based on MS SQL functionality, but other "correct" DBMSs have analogues. :)


Thanks for your hints! Sounds principle good, but we should have (if possible) a database independent aproach ...

Does anyone know a possiblity in nhibernate itself?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 10:03 am 
Newbie

Joined: Thu May 19, 2005 6:04 am
Posts: 14
Location: Glasgow, UK
What I have is as follows:

I have an InUse property (0 = deleted,1=inuse)

I have in my mappings the where attribute set (i.e.

<class name="MyType" table="MYTABLE" where="INUSE=1">
)

from running trace this gets added to any queries to populate objects.

my delete functions set the Inuse property to false, then save, and the object is no longer visible to nhibernate.

Just make sure all collection properties have the attribute set as well 9so bags sets etc).

May not be the best solution but it's working great on a several million row (with CLOB properties) db.

Hope this helps

mark


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 10:11 am 
Regular
Regular

Joined: Fri Jun 11, 2004 6:27 am
Posts: 81
Location: Yaroslavl, Russia
CrossFair wrote:
Thanks for your hints! Sounds principle good, but we should have (if possible) a database independent aproach ...


Well, if you want independency (though database independency is a myth, of course :-)) then you can still use view, as it's common database feature. You mustn't use ISession.Delete method, but instead have to mark object as deleted and save it to the database. I think it's also appropriate to evict it from session and second-level cache.

_________________
Best,
Andrew Mayorov // BYTE-force


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 15, 2006 3:53 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
Do you really want to describe the row as "deleted"? I've seen this issue addressed as you mention, by adding a boolean column to the table, but calling it "inactive". Only certain queries (or database views) would filter out the inactive records, since they still need to be retrieved in general when accessing legacy data. The only general effects of an inactive record would be that it is not updateable and cannot be newly associated with other records, new or existing.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 16, 2006 2:39 am 
Newbie

Joined: Mon Jan 30, 2006 9:15 am
Posts: 11
Nels_P_Olsen wrote:
Do you really want to describe the row as "deleted"?

Yes that is the reason ... In normal case the "deleted/inactiv" records should never been returned to the application.

The rows should only exists for historicaly reason and eg. if something goes wrong, we have the possibility to restore/repair the currupt data (manually in database).

Through a job the "deleted/incative" rows can be deleted (based on a timestamp) after a certain time.

Is this an unusual approach?

Regards,
Cross


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 16, 2006 5:06 am 
Regular
Regular

Joined: Fri Jun 11, 2004 6:27 am
Posts: 81
Location: Yaroslavl, Russia
CrossFair, marking objects as deleted works well only to certain extents. With growth of your archive, database will perform slower and slower. It's not an issue if you have hundreds of records, but with hundreds of thousands you can have problems. (Real numbers depend on the speed of the server). So in general it's better to move deleted records into special archive table. You can even have several such tables, split into years, months or other periods.

_________________
Best,
Andrew Mayorov // BYTE-force


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