-->
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: One-shot-delete for collection of composite-id classes
PostPosted: Sat Mar 22, 2008 8:41 pm 
Newbie

Joined: Mon Mar 17, 2008 3:36 pm
Posts: 4
I've been spiking NHibernate for a large enterprise application. This means I'm a total newbie. We need to integrate a legacy database into our system.

I have a class DraftAuthorization wich has a collection of PermissionOnFunctionality object (composite id in the DB). Each PermissionOnFunctionality object also has a collection of PermissionOnSecurityToken objects (also a composite id in the DB). When I remove a PermissionOnFunctionality object, I want to also remove all of it's containing PermissionOnSecurityToken objects. I was hoping that this could be achieved by a one-shot-delete, but instead, NHibernate deletes each PermissionOnSecurityToken one by one.

Is a one-shot delete possible, and if so, what am I doing wrong? I'm using NHibernate 1.2.1.

Here is the mapping file:

Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
   <class name="NHibernateSpike.Domain.Model.ActiveAuthorization, NHibernateSpike"
           table="Authorization"
           lazy="false">
      <id name="Id" type="Int64" unsaved-value="-1" access="field.camelcase-underscore">
         <column name="Id" sql-type="decimal" not-null="true" unique="true"/>
         <generator class="native"/>
      </id>
      <many-to-one name="Draft"
                     class="NHibernateSpike.Domain.Model.DraftAuthorization, NHibernateSpike"
                     column="Draft"
                     access="field.camelcase-underscore"
                     cascade="all"/>
   </class>
   
   <class name="NHibernateSpike.Domain.Model.DraftAuthorization, NHibernateSpike"
           table="Authorization"
           lazy="false">
      <id name="Id" type="Int64" unsaved-value="-1" access="field.camelcase-underscore">
         <column name="Id" sql-type="decimal" not-null="true" unique="true"/>
         <generator class="native"/>
      </id>
      <set name="PermissionsOnFunctionality" access="field.camelcase-underscore"
          lazy="false" cascade="all-delete-orphan" inverse="true">
            <key>
                <column name="AuthorizationId"/>
            </key>
            <one-to-many class="NHibernateSpike.Domain.Model.PermissionOnFunctionality, NHibernateSpike"/>
        </set>
   </class>
   
   <class name="NHibernateSpike.Domain.Model.PermissionOnFunctionality, NHibernateSpike"
           table="PermissionOnFunctionality" lazy="false">
      <composite-id name="PofKey" class="NHibernateSpike.Domain.Model.PofKey, NHibernateSpike" access="field.camelcase-underscore">
            <key-property name="AuthorizationId" access="field.camelcase-underscore" column="AuthorizationId" type="Int64"/>
            <key-property name="FunctionalityCode" access="field.camelcase-underscore" column="FunctionalityCode" type="String"/>
      </composite-id>
      <timestamp name="LastChange" column="LastChange"/>
        <many-to-one name="Functionality" column="FunctionalityCode" class="NHibernateSpike.Domain.Model.Functionality, NHibernateSpike"
                     access="field.camelcase-underscore" lazy="false" cascade="none" insert="false" update="false"/>
      <property name="AccessCode" column="AccessCode"  not-null="true"/>
      <property name="Creation" column="CreationDate" type="DateTime" not-null="true"/>
      <property name="CreatedBy" column="CreationUser" type="String" not-null="true"/>
      <property name="LastChangedBy" column="LastChangeUser" type="String" not-null="true"/>
      <set name="PermissionsOnSecurityToken" access="field.camelcase-underscore"
          lazy="false" cascade="all-delete-orphan" inverse="true" optimistic-lock="false">
            <key>
            <column name="AuthorizationId"/>
            <column name="FunctionalityCode"/>
            </key>
            <one-to-many class="NHibernateSpike.Domain.Model.PermissionOnSecurityToken, NHibernateSpike"/>
        </set>
   </class>
   
   <class name="NHibernateSpike.Domain.Model.PermissionOnSecurityToken, NHibernateSpike"
           table="PermissionOnSecurityToken" lazy="false">
        <composite-id name="PosKey" class="NHibernateSpike.Domain.Model.PosKey, NHibernateSpike" access="field.camelcase-underscore">
            <key-property name="AuthorizationId" column="AuthorizationId" type="Int64" access="field.camelcase-underscore"/>
            <key-property name="FunctionalityCode" column="FunctionalityCode" type="String" access="field.camelcase-underscore"/>
            <key-property name="SecurityToken" column="SecurityToken" type="String" access="field.camelcase-underscore"/>
        </composite-id>
        <timestamp name="LastChange" column="LastChange"/>
        <many-to-one name="Functionality" column="FunctionalityCode" class="NHibernateSpike.Domain.Model.Functionality, NHibernateSpike"
                     access="field.camelcase-underscore" lazy="false" cascade="none" insert="false" update="false"/>
      <property name="AccessCode" column="AccessCode"  not-null="true"/>
      <property name="Creation" column="CreationDate" type="DateTime" not-null="true"/>
      <property name="CreatedBy" column="CreationUser" type="String" not-null="true"/>
      <property name="LastChangedBy" column="LastChangeUser" type="String" not-null="true"/>
   </class>

    <class name="NHibernateSpike.Domain.Model.Functionality, NHibernateSpike"
           table="Functionality"
           lazy="false">
      <id name="Code" type="String" access="field.camelcase-underscore">
         <column name="Code" sql-type="char" length="20" not-null="true" unique="true"/>
         <generator class="assigned"/>
      </id>
   </class>
</hibernate-mapping>


And here is the code (please ignore the quality: it's part of a spike, so its throw-away code):

Code:
//
// Authorization
//
public abstract class Authorization
{
    private readonly Int64 _id;
  private ISet<PermissionOnFunctionality> _permissionsOnFunctionality;
 
    protected void AddPermissionOnFunctionality(PermissionOnFunctionality permissionOnFunctionality)
    {
        _permissionsOnFunctionality.Add(permissionOnFunctionality);
    }

    protected void RemovePermissionOnFunctionality(PermissionOnFunctionality permissionOnFunctionality)
    {
  _permissionsOnFunctionality.Remove(permissionOnFunctionality);
    }

    public Int64 Id
    {
        get { return _id; }
    }

    public IEnumerable<PermissionOnFunctionality> PermissionsOnFunctionality
    {
        get
        {
    if(null == _permissionsOnFunctionality)
    {
      _permissionsOnFunctionality = new HashedSet<PermissionOnFunctionality>();
    }
   
          return _permissionsOnFunctionality;
        }
    }
}

//
// ActiveAuthorization
//
public class ActiveAuthorization : Authorization
{
    private DraftAuthorization _draft;

    public DraftAuthorization Draft
    {
        get { return _draft; }
    }
}

//
// DraftAuthorization
//
public class DraftAuthorization : Authorization
{
    private DateTime _expirationDate;

    private PermissionOnFunctionality FindPermissionOnFunctionality(Functionality functionality)
    {
  return Algorithms.FindFirstWhere(PermissionsOnFunctionality,
                                   delegate(PermissionOnFunctionality permissionOnFunctionality)
                                   {
                                      return permissionOnFunctionality.Functionality.Code ==
                                             functionality.Code;
                                   });
    }
   
    private PermissionOnSecurityToken FindPermissionOnSecurityToken(PermissionOnFunctionality permissionOnFunctionality,
                                String securityToken)
    {
      return Algorithms.FindFirstWhere(permissionOnFunctionality.PermissionsOnSecurityToken,
                       delegate(PermissionOnSecurityToken permissionOnSecurityToken)
                       {
                        return permissionOnSecurityToken.SecurityToken == securityToken;
                       });
    }

  public DraftAuthorization()
    {
        _expirationDate = DateTime.Today.AddDays(1);
    }

    public DateTime ExpirationDate
    {
        get { return _expirationDate; }
        set { _expirationDate = value; }
    }

    public void GrantPermissionTo(Functionality functionality, Int32 accessCode)
    {
        PermissionOnFunctionality permissionOnFunctionality = FindPermissionOnFunctionality(functionality);
        if(null == permissionOnFunctionality)
        {
            PermissionOnFunctionality newPermissionOnFunctionality = new PermissionOnFunctionality(this, functionality, accessCode);
          newPermissionOnFunctionality.ValidFrom = DateTime.Now;
          newPermissionOnFunctionality.ValidTo = DateTime.Now.AddDays(6);
          newPermissionOnFunctionality.Creation = DateTime.Now;
          newPermissionOnFunctionality.CreatedBy = "SOMEUSER";
            newPermissionOnFunctionality.LastChangedBy = "SOMEUSER";
         
            AddPermissionOnFunctionality(newPermissionOnFunctionality);
        }
        else
        {
            permissionOnFunctionality.AccessCode = accessCode;           
        }
    }
   
    public void GrantPermissionTo(String securityToken, Functionality functionality, Int32 accessCode)
    {
      PermissionOnFunctionality permissionOnFunctionality = FindPermissionOnFunctionality(functionality);
      if(null != permissionOnFunctionality)
      {
        PermissionOnSecurityToken permissionOnSecurityToken = FindPermissionOnSecurityToken(permissionOnFunctionality, securityToken);
        if(null == permissionOnSecurityToken)
    {
                PermissionOnSecurityToken newPermissionOnSecurityToken = new PermissionOnSecurityToken(this, functionality, securityToken, accessCode);
            newPermissionOnSecurityToken.Creation = DateTime.Now;
                newPermissionOnSecurityToken.CreatedBy = "SOMEUSER";
                newPermissionOnSecurityToken.LastChangedBy = "SOMEUSER";
           
      permissionOnFunctionality.GrantPermissionOnSecurityToken(newPermissionOnSecurityToken);
    }
    else
    {
      permissionOnSecurityToken.AccessCode = accessCode;           
    }
      }
    }

  public void RevokePermissionTo(Functionality functionality)
    {
        PermissionOnFunctionality permissionOnFunctionality = FindPermissionOnFunctionality(functionality);
        if(null != permissionOnFunctionality)
        {
            permissionOnFunctionality.RevokeAllPermissionsOnSecurityToken();
            RemovePermissionOnFunctionality(permissionOnFunctionality);
        }
    }
   
    public void RevokePermissionTo(String securityToken, Functionality functionality)
    {
        PermissionOnFunctionality permissionOnFunctionality = FindPermissionOnFunctionality(functionality);
        if(null != permissionOnFunctionality)
        {
    PermissionOnSecurityToken permissionOnSecurityToken = FindPermissionOnSecurityToken(permissionOnFunctionality, securityToken);
        if(null != permissionOnSecurityToken)
        {
          permissionOnFunctionality.RevokePermissionOnSecurityToken(permissionOnSecurityToken);
        }
        }
    }
}

public interface IAuditable
{
  DateTime Creation
  { get; set; }
 
  String CreatedBy
  { get; set; }

  DateTime LastChange
  { get; set; }
 
  String LastChangedBy
  { get; set; }
}

public abstract class Permission : IAuditable
{
  private Int32 _accessCode;
  private readonly Functionality _functionality;
 
  private DateTime _lastChange = DateTime.MinValue;
    private DateTime _creation;
    private String _createdBy;
    private String _lastChangedBy;

  protected internal Permission()
  {}

  protected Permission(Functionality functionality, Int32 accessCode)
  {
    _functionality = functionality;
    _accessCode = accessCode;
  }

  public Int32 AccessCode
  {
    get { return _accessCode; }
    set { _accessCode = value; }
  }
 
  public Functionality Functionality
  {
    get { return _functionality; }
  }
 
  #region IAuditable Members

    public DateTime Creation
    {
      get { return _creation; }
      set { _creation = value; }
    }

    public String CreatedBy
    {
      get { return _createdBy; }
      set { _createdBy = value; }
    }

    public DateTime LastChange
    {
      get { return _lastChange; }
      set { _lastChange = value; }
    }

    public String LastChangedBy
    {
      get { return _lastChangedBy; }
      set { _lastChangedBy = value; }
    }

    #endregion
}

  public class PofKey
  {
      private readonly Int64 _authorizationId;
      private readonly String _functionalityCode;

      protected internal PofKey()
      {}

      public PofKey(Int64 authorizationId, String functionalityCode)
      {
          _authorizationId = authorizationId;
          _functionalityCode = functionalityCode;
      }

      public Int64 AuthorizationId
      {
          get { return _authorizationId; }
      }

      public String FunctionalityCode
      {
          get { return _functionalityCode; }
      }

      public override Boolean Equals(Object obj)
      {
          // Check for null reference or different type
          PofKey other = obj as PofKey;
          if(null == other || GetType() != other.GetType())
          {
              return false;
          }

          // Check for same object reference
          if(this == other)
          {
              return true;
          }

          return (_functionalityCode == other.FunctionalityCode) &&
                 (_authorizationId == other.AuthorizationId);
      }

      public override Int32 GetHashCode()
      {
          return FunctionalityCode.GetHashCode() ^ AuthorizationId.GetHashCode();
      }
  }

  public class PermissionOnFunctionality : Permission
  {
      private readonly PofKey _pofKey;
    private DateTime _validFrom;
    private DateTime _validTo;
    private ISet<PermissionOnSecurityToken> _permissionsOnSecurityToken;
 
  internal void GrantPermissionOnSecurityToken(PermissionOnSecurityToken permissionOnSecurityToken)
      {
          _permissionsOnSecurityToken.Add(permissionOnSecurityToken);
      }

    internal void RevokePermissionOnSecurityToken(PermissionOnSecurityToken permissionOnSecurityToken)
      {
    _permissionsOnSecurityToken.Remove(permissionOnSecurityToken);
      }
 
    internal PermissionOnFunctionality()
  {}
     
      public PermissionOnFunctionality(Authorization authorization, Functionality functionality, Int32 accessCode)
    : base(functionality, accessCode)
      {
          _pofKey = new PofKey(authorization.Id, functionality.Code);   
      }

  public IEnumerable<PermissionOnSecurityToken> PermissionsOnSecurityToken
      {
          get
          {
      if(null == _permissionsOnSecurityToken)
      {
        _permissionsOnSecurityToken = new HashedSet<PermissionOnSecurityToken>();
      }
     
            return _permissionsOnSecurityToken;
          }
      }

    public DateTime ValidFrom
    {
      get { return _validFrom.Date; }
      set { _validFrom = value.Date; }
    }

    public DateTime ValidTo
    {
      get { return _validTo.Date; }
      set { _validTo = value.Date; }
    }
   
    public override Boolean Equals(Object obj)
  {
      // Check for null reference or different type
      PermissionOnFunctionality other = obj as PermissionOnFunctionality;
      if(null == other || GetType() != other.GetType())
      {
          return false;
      }

      // Check for same object reference
      if(this == other)
      {
          return true;
      }

      return _pofKey.Equals(other._pofKey);
  }

  public override Int32 GetHashCode()
  {
      return _pofKey.GetHashCode();
  }

      public void RevokeAllPermissionsOnSecurityToken()
      {
          ISet<PermissionOnSecurityToken> temp = new HashedSet<PermissionOnSecurityToken>(_permissionsOnSecurityToken);
          _permissionsOnSecurityToken.RemoveAll(temp);
      }
  }
 
  public class PosKey : PofKey
  {
      private readonly String _securityToken;

      protected internal PosKey()
      {}

      public PosKey(Int64 authorizationId, String functionalityCode, String securityToken)
          : base(authorizationId, functionalityCode)
      {
          _securityToken = securityToken;
      }

      public String SecurityToken
      {
          get { return _securityToken; }
      }

      public override Boolean Equals(Object obj)
      {
          // Check for null reference or different type
          PosKey other = obj as PosKey;
          if(null == other || GetType() != other.GetType())
          {
              return false;
          }

          // Check for same object reference
          if(this == other)
          {
              return true;
          }

          return base.Equals(other) &&
                 (_securityToken == other.SecurityToken);
      }

      public override Int32 GetHashCode()
      {
          return base.GetHashCode() ^ SecurityToken.GetHashCode();
      }
  }

  public class PermissionOnSecurityToken : Permission
  {
      private readonly PosKey _posKey;

      internal PermissionOnSecurityToken()
      { }

      public PermissionOnSecurityToken(Authorization authorization, Functionality functionality, String securityToken, Int32 accessCode)
          : base(functionality, accessCode)
      {
          _posKey = new PosKey(authorization.Id, functionality.Code, securityToken);
      }

      public String SecurityToken
      {
          get { return _posKey.SecurityToken; }
      }

      public override Boolean Equals(Object obj)
      {
          // Check for null reference or different type
          PermissionOnSecurityToken other = obj as PermissionOnSecurityToken;
          if(null == other || GetType() != other.GetType())
          {
              return false;
          }

          // Check for same object reference
          if(this == other)
          {
              return true;
          }

          return _posKey.Equals(other._posKey);
      }

      public override Int32 GetHashCode()
      {
          return _posKey.GetHashCode();
      }
  }

//
// AuthorizationService
//
public class AuthorizationService
{
  private readonly IAuthorizationRepository _authorizationRepository;
  private readonly IFunctionalityRepository _functionalityRepository;

  public AuthorizationService(IAuthorizationRepository authorizationRepository,
                              IFunctionalityRepository functionalityRepository)
  {
    _authorizationRepository = authorizationRepository;
    _functionalityRepository = functionalityRepository;
  }

  public void SaveAuthorization()
  {
    ActiveAuthorization activeAuthorization = _authorizationRepository.GetActiveAuthorizationFor(1);

    Functionality functionality1 = _functionalityRepository.GetFunctionalityFor("F1000");
    //activeAuthorization.Draft.GrantPermissionTo(functionality1, 1);
    //activeAuthorization.Draft.RevokePermissionTo(functionality1);

    //activeAuthorization.Draft.GrantPermissionTo("SEC_Token1", functionality1, 2);
    //activeAuthorization.Draft.GrantPermissionTo("SEC_Token2", functionality1, 4);
   
    Functionality functionality3 = _functionalityRepository.GetFunctionalityFor("F1001");
    //activeAuthorization.Draft.GrantPermissionTo(functionality3, 3);
    activeAuthorization.Draft.RevokePermissionTo(functionality3);

      //activeAuthorization.Draft.GrantPermissionTo("Token2", functionality3, 4);
    //activeAuthorization.Draft.GrantPermissionTo("Token3", functionality3, 2);
      //activeAuthorization.Draft.GrantPermissionTo("Token1", functionality3, 3);

     //activeAuthorization.Draft.RevokePermissionTo("Token1", functionality3);
      //activeAuthorization.Draft.RevokePermissionTo("Token2", functionality3);

    _authorizationRepository.Save(activeAuthorization);
  }
}

//
// AuthorizationRepository
//
public class AuthorizationRepository : IAuthorizationRepository
{
  private readonly ISessionManager _sessionManager;

    public AuthorizationRepository(ISessionManager sessionManager)
    {
      _sessionManager = sessionManager;
      _sessionManager.DefaultFlushMode = FlushMode.Never;
    }

    public ActiveAuthorization GetActiveAuthorizationFor(Int64 id)
    {
      ISession session = _sessionManager.OpenSession();
  return session.Get<ActiveAuthorization>(id);
    }

    public void Save(ActiveAuthorization activeAuthorization)
    {
  ISession session = _sessionManager.OpenSession();

    session.SaveOrUpdate(activeAuthorization);
    session.Flush();

    }
}


I'm using a SqLite database (for testing purposes).

[code]CREATE TABLE [Authorization] (
[Id] INTEGER NULL,
[ExpirationDate] DATE NULL,
[Draft] INTEGER NULL
);

CREATE TABLE [Functionality] (
[code] VARCHAR(30) NOT NULL PRIMARY KEY
);

CREATE TABLE [PermissionOnFunctionality] (
[AuthorizationId] INTEGER NOT NULL,
[FunctionalityCode] VARCHAR(30) NOT NULL,
[AccessCode] INTEGER NULL,
[LastChange] TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
[LastChangeUser] VARCHAR(30) NOT NULL,
[CreationDate] TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
[CreationUser] VARCHAR(30) NOT NULL,
PRIMARY KEY ([AuthorizationId],[FunctionalityCode])
)

CREATE TABLE [PermissionOnSecurityToken] (
[AuthorizationId] INTEGER NOT NULL,
[FunctionalityCode] VARCHAR(30) NOT NULL,
[SecurityToken] VARCHAR(30) NOT NULL,
[AccessCode] INTEGER NOT NULL,
[LastChange] TIMESTAMP NOT NULL,
[LastChangeUser] VARCHAR(30) NOT NULL,
[CreationDate] TIMESTAMP NOT NULL,
[CreationUser] VARCHAR(30) NOT NULL,
PRIMARY KEY ([AuthorizationId],[FunctionalityCode],[SecurityToken])
)[/code]


This is a piece of the SQL that gets generated:

[code]...

NHibernate: DELETE FROM PermissionOnSecurityToken WHERE AuthorizationId = @p0 AN
D FunctionalityCode = @p1 AND SecurityToken = @p2 AND LastChange = @p3; @p0 = '2
', @p1 = 'F1001', @p2 = 'Token3', @p3 = '23/03/2008 1:36:56'
NHibernate: DELETE FROM PermissionOnSecurityToken WHERE AuthorizationId = @p0 AN
D FunctionalityCode = @p1 AND SecurityToken = @p2 AND LastChange = @p3; @p0 = '2
', @p1 = 'F1001', @p2 = 'Token1', @p3 = '23/03/2008 1:36:56'
NHibernate: DELETE FROM PermissionOnSecurityToken WHERE AuthorizationId = @p0 AN
D FunctionalityCode = @p1 AND SecurityToken = @p2 AND LastChange = @p3; @p0 = '2
', @p1 = 'F1001', @p2 = 'Token2', @p3 = '23/03/2008 1:36:56'
NHibernate: DELETE FROM PermissionOnFunctionality WHERE AuthorizationId = @p0 AN
D FunctionalityCode = @p1 AND LastChange = @p2; @p0 = '2', @p1 = 'F1001', @p2 =
'23/03/2008 1:36:56'[/code]

Notice that there are three deletes on PermissionOnSecurityToken before the delete on PermissionOnFunctionality. I guess this could be done with a single delete statement for PermissionOnSecurityToken. Any suggestions?

Thanks in advance,

Jan


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 24, 2008 10:53 am 
Newbie

Joined: Mon Jul 14, 2008 5:17 am
Posts: 3
i have this problem too. But i can't find any solution.


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.