简体   繁体   English

在NHibernate中使用自定义SQL加载集合

[英]Load collection with custom SQL in NHibernate

I'm pretty new to NHibernate. 我对NHibernate很新。 I understood the main concepts, but now I'm a bit stuck : I need to load a collection property using a slightly complicated SQL query. 我理解了主要概念,但现在我有点卡住:我需要使用稍微复杂的SQL查询加载集合属性。 Let me explain: I'm writing a code generator that generates classes from Oracle tables (using oracle TAB and COL views). 让我解释一下:我正在编写一个代码生成器,它从Oracle表生成类(使用oracle TAB和COL视图)。 So basically, I have two classes, Table and Column, described like this: 所以基本上,我有两个类,表和列,描述如下:

public class Table
{
    public virtual String Name { get; set; }
    public virtual ISet<Column> Columns { get; set; }
    public virtual ISet<Column> PrimaryKeys { get; set; } 
}

public class Column
{
    public virtual Table Table { get; set; }
    public virtual String TableName { get; set; }
    public virtual String Name { get; set; }
    public virtual String Type{ get; set; }

    public override bool Equals(object obj)
    {
        Column c = obj as Column;
        if (obj == null)
            return false;

        return c.Table == Table && c.Name == Name;
    }

    public override int GetHashCode()
    {
        return (this.TableName.GetHashCode() + Name.GetHashCode()).GetHashCode();
    }
}

The mapping xml files are straightforward: 映射xml文件很简单:

Table.hbm.xml : Table.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="ModelGenerator" namespace="ModelGenerator.Models">
  <class name="Table" table="TAB">

    <id name="Name" column="TNAME"></id>

    <set name="Columns" order-by="COLNO">
      <key>
        <column name="TNAME"></column>
      </key>
      <one-to-many class="Column"></one-to-many>
    </set>

  </class>

</hibernate-mapping>

Column.hbm.xml : Column.hbm.xml:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="ModelGenerator" namespace="ModelGenerator.Models">
  <class name="Column" table="COL">

    <composite-id>
      <key-property name="TableName" column="TNAME"></key-property>
      <key-property name="Name" column="CNAME"></key-property>
    </composite-id>

    <property name="Type" column="COLTYPE"></property>

    <many-to-one name="Table">
      <column name="TNAME"></column>
    </many-to-one>

  </class>

</hibernate-mapping>

Now I'd like to add in the class Table a collection that contains the primary keys. 现在我想在类Table中添加一个包含主键的集合。 I can get the primary key columns with the following query : 我可以使用以下查询获取主键列:

SELECT col.tname, col.cname, col.coltype
FROM all_constraints cons, all_cons_columns cons_cols, col
WHERE cons_cols.table_name = :MY_TABLE
and   cons_cols.OWNER = :MY_ORACLE_USER
AND cons.constraint_type = 'P'
AND cons.constraint_name = cons_cols.constraint_name
AND cons.owner = cons_cols.owner
and col.tname = cons_cols.table_name
and col.cname = cons_cols.column_name
ORDER BY cons_cols.table_name, cons_cols.position

The results of this query could be mapped with my Column class. 可以使用我的Column类映射此查询的结果。 Ideally, my Table class would be now : 理想情况下,我的Table类现在是:

public class Table
{
    public virtual String Name { get; set; }
    public virtual ISet<Column> Columns { get; set; }
    public virtual ISet<Column> PrimaryKeys { get; set; } 
}

My problem is that I can't see how to declare this SQL query in my Table.hbm.xml file. 我的问题是我无法看到如何在Table.hbm.xml文件中声明此SQL查询。 I saw the <sql-query> and <load-collection> elements in the documentation but I can't make it work as I want... 我在文档中看到了<sql-query>和<load-collection>元素,但我无法按照我的意愿使其工作...

Does anyone know how to achieve this? 有谁知道如何实现这一目标?

Many thanks, 非常感谢,

Nico 尼科

Well, finally I found my problem :) 好吧,最后我发现了我的问题:)

It was mainly caused by the <sql-query> element that I put inside the <class> element. 它主要是由我放在<class>元素中的<sql-query>元素引起的。 NHibernate was unable to find it there. NHibernate无法在那里找到它。

So I kept the Table.cs as is, and now my Table.hbm.xml looks is the following: 所以我保持Table.cs不变,现在我的Table.hbm.xml看起来如下:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="ModelGenerator" namespace="ModelGenerator.Models">
  <class name="Table" table="TAB">

    <id name="Name" column="TNAME"></id>

    <set name="Columns" order-by="COLNO">
      <key>
        <column name="TNAME"></column>
      </key>
      <one-to-many class="Column"></one-to-many>
    </set>

    <set name="PrimaryKeys">
      <key>
        <column name="TNAME"></column>
      </key>
      <one-to-many class="Column"/>
      <loader query-ref="primarykeys"/>
    </set>

  </class>

  <sql-query name="primarykeys">

    <load-collection alias="col" role="Table.PrimaryKeys"/>

    SELECT col.tname, col.colno, col.cname, col.coltype, col.width, col.scale, col.precision, col.nulls, col.defaultval, col.character_set_name
      FROM all_constraints cons, all_cons_columns cons_cols, col
      WHERE cons_cols.table_name = ?
      and   cons_cols.OWNER = 'MY_ORACLE_USER'
      AND cons.constraint_type = 'P'
      AND cons.constraint_name = cons_cols.constraint_name
      AND cons.owner = cons_cols.owner
      and col.tname = cons_cols.table_name
      and col.cname = cons_cols.column_name
      ORDER BY cons_cols.table_name, cons_cols.position
  </sql-query>

</hibernate-mapping>

It works! 有用! I hope it can help anyone. 我希望它可以帮助任何人。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM