One to many association in Hibernate without composite key

Table:

tradeId | actionTradeId | type | date

where tradeId+actionTradeId - composite key

Hibernate mapping:

<class name="Trade" table="TRADE">
 <composite-id name="id" class="TradePK">
        <key-property name="tradeId" type="long" column="trade_id"/>
        <key-property name="actionTradeId" type="long"        column="action_trade_id"/>
  </composite-id>
<property name="type" length="1"/>
<property name="date"/>
</class>

What I need

I want to have mapping on the same table like in this query:

select * 
from Trade 
where action_trade_id = trade_id and type = 'S'

First I tried this way, but it fails because I have composite key:

<set name="sellTrades" inverse="false" lazy="true" where="type='S'">
            <key>
                <column name="action_trade_id" not-null="true" />
            </key>
            <one-to-many class="Trade" />
</set>

Sample data:

 tradeId| actionTradeId | type| date 
 --------------------------------------
    11         22          S    date (so for this entity I need list with <55, 66>)
    33         44          S    date 
    55         11          S    date
    66         11          S    date

Answers


public class ClassWithCompositeKey
{
    private int id1;
    private int id2;

    public ClassWithCompositeKey()
    {
        Children = new List<ClassWithCompositeKey>();
    }

    public virtual int Id1
    {
        get { return id1; }
        set { id1 = value; }
    }
    public virtual int Id2
    {
        get { return id2; }
        set { id2 = value; }
    }

    public virtual string Type { get; set; }

    public virtual ICollection<ClassWithCompositeKey> Children { get; protected set; }

    public override bool Equals(object obj)
    {
        var other = obj as ClassWithCompositeKey;
        return other != null && Id1 == other.Id1 && Id2 == other.Id2;
    }

    public override int GetHashCode()
    {
        return (Id1 << 16) | Id2;  // optimized for Id's < 16 bit
    }
}

mapping

public class ClassWithCompositeKeyMap : ClassMap<ClassWithCompositeKey>
{
    public ClassWithCompositeKeyMap()
    {
        CompositeId()
            .KeyProperty(x => x.Id1)
            .KeyProperty(x => x.Id2);

        Map(x => x.Type);

        Map(x => id1).Column("Id1").Access.Using("field").ReadOnly();

        HasMany(x => x.Children)
            .Where("Type = 'S'")
            .PropertyRef("id1")
            .KeyColumns.Add("Id2")
            .Inverse();
    }

    public virtual int id1 { get; set; }
}

and query

using (var tx = session.BeginTransaction())
{
    session.Save(new ClassWithCompositeKey { Id1 = 11, Id2 = 22, Type = "F" });
    session.Save(new ClassWithCompositeKey { Id1 = 55, Id2 = 11, Type = "S" });
    session.Save(new ClassWithCompositeKey { Id1 = 66, Id2 = 11, Type = "S" });
    tx.Commit();
}
session.Clear();

var x = session.Get<ClassWithCompositeKey>(new ClassWithCompositeKey { Id1 = 11, Id2 = 22 });
Assert.Equal(2, x.Children.Count);

Note

  • lazyloading for the collection is disabled because of property-ref
  • be carefull to sync the Children collection with instances which should belong in it in code so you won't have a broken model

Update as hbm

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="ClassWithCompositeKey">
    <composite-id>
      <key-property name="Id1" column="Id1"/>
      <key-property name="Id2" column="Id2"/>
    </composite-id>
    <bag inverse="true" lazy="true" name="Children" where="Type = 'S'">
      <key property-ref="id1">
        <column name="Id2" />
      </key>
      <one-to-many class="ClassWithCompositeKey" />
    </bag>
    <property name="Type" column="Type" />
    <property access="field" name="id1" column="id1" insert="false" update="false"/>
  </class>
</hibernate-mapping>

Need Your Help


About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.