1. 程式人生 > >nhibernate一表對應多個實體類問題

nhibernate一表對應多個實體類問題

應用了NHIBERNATE的web頁面忽然報錯:未明確定義列。
將NHIBERNATE生成的SQL語句拿出來直接執行,發現裡面有兩個欄位的名字一樣,類似:

select row_.* from 
( select meta0_.ID as ID6_, meta0_.NAME as NAME6_, 
  meta0_.PARENTID as PARENTID6_,meta0_.ParentID as ParentID6_  --這兩個欄位名字一樣!!!
  from work.Meta meta0_ where meta0_.CATEGORY=21 order by meta0_.ID asc 
) row_ 
where rownum <=20

為何出現有名字一樣的情況?原因在於實體類裡,有一個指向自身的屬性:

實體類

    [Serializable]
    public partial class Meta
    {
		public virtual int ID { get; set; }
        public virtual string NAME { get; set; }
        public virtual int PARENTID { get; set; }
        public virtual Meta Parent { get; set; }//這是一個樹形的結構,父物件parent也是同一型別。換言之,這個屬性指向了自己
    }

對映

	public partial class MetaMap : ClassMap<Meta>
    {
        public MetaMap()
        {
            Table("Meta");
            Id(s => s.ID);
            Map(s => s.NAME);
            Map(s => s.PARENTID);
            References(s => s.Parent).Column("ParentID")
                .LazyLoad()
                .NotFound.Ignore();
        }
    }

針對這種情況,有兩種處理辦法。

辦法一:
在對映裡,將parentId的對映取消,如果要訪問這個欄位,就要用Parent.ID來代替。問題是,並非所有記錄都有父物件,最頂層的節點是沒有父物件的。

	public partial class MetaMap : ClassMap<Meta>
    {
        public MetaMap()
        {
            Table("Meta");
            Id(s => s.ID);
            Map(s => s.NAME);
            //Map(s => s.PARENTID);//取消這個對映,要訪問此屬性,用Parent.ID來代替
            References(s => s.Parent).Column("ParentID")
                .LazyLoad()
                .NotFound.Ignore();
        }
    }

辦法二:
宣告一個新的實體類MetaPro,避免指向自身

實體類一分為二
    [Serializable]
    public partial class Meta
    {
		public virtual int ID { get; set; }
        public virtual string NAME { get; set; }
        public virtual int PARENTID { get; set; }
    }
    
    [Serializable]
    public partial class MetaPro
    {
		public virtual int ID { get; set; }
        public virtual string NAME { get; set; }
        public virtual int PARENTID { get; set; }
        public virtual Meta Parent { get; set; }//指向的是Meta,而不是自己
    }

相應的對映

	public partial class MetaMap : ClassMap<Meta>
    {
        public MetaMap()
        {
            Table("Meta");
            Id(s => s.ID);
            Map(s => s.NAME);
            Map(s => s.PARENTID);
        }
    }
    
   public partial class MetaProMap : ClassMap<MetaPro>
    {
        public MetaProMap()
        {
            Table("Meta");
            Id(s => s.ID);
            Map(s => s.NAME);
            Map(s => s.PARENTID);
            References(s => s.Parent).Column("ParentID")
                .LazyLoad()
                .NotFound.Ignore();
        }
    }

注意實體類之間不能繼承。原本很自然想到,實體類應該這樣定義:

//根本行不通
    [Serializable]
    public partial class Meta
    {
		public virtual int ID { get; set; }
        public virtual string NAME { get; set; }
        public virtual int PARENTID { get; set; }
    }
    
    [Serializable]
    public partial class MetaPro : Meta
    {
        public virtual Meta Parent { get; set; }//指向的是Meta,而不是自己
    }

但出現的結果卻是,原本使用meta的地方,系統全部自動用到了MetaPro。為何如此,令人困惑,這個要看nhibernate自己的解釋機制。

相關推薦

nhibernate對應實體問題

應用了NHIBERNATE的web頁面忽然報錯:未明確定義列。 將NHIBERNATE生成的SQL語句拿出來直接執行,發現裡面有兩個欄位的名字一樣,類似: select row_.* from ( select meta0_.ID as ID6_, meta0

Spring Data JPA 實體聯合視圖查詢

test where part 左連接 lec 視圖 view new manytoone Spring Data JPA 查詢數據庫時,如果兩個表有關聯,那麽就設個外鍵,在查詢的時候用Specification創建Join 查詢便可。但是只支持左連接,不支持右連接,雖說左

Python 字典中對應

列表 檢查 span mark blog class efault remove one #字典的一鍵多值 print‘方案一 list作為dict的值 值允許重復‘ d1={} key=1 value=2 d1.setdefault(key

EF基礎知識小記七(拆分實體以及拆分實體)

style 需要 性能 rri pub chang 常用 日常 ted 一、拆分實體到多個表 1、在日常開發中,會經常碰到一些老系統,當客戶提出一些新的需求,這些需求需要在原來的表的基礎上加一些字段,大多數人會選擇通過給原表添加字段的方式來完成這些需求,方法,雖然可行,但是

後臺解析JSON實體資料

最近想用JSON傳送1次傳送多個數據回後臺的時候,涉及到不同的表引數。網上找的解析JSON的例子大多引數都是物件。或者JSON裡面的引數都是和類的屬性對應的。但是我想要傳的是引數是在不同的類裡面的。我又不想用引數的形式多次分別傳。就想用JSON一起傳然後分別解析。 難道我每一個涉及到不同類的引數都要新建一個

【laravel】 複雜單請求驗證,實現一個對應

一、序言 laravel 中提供了兩種驗證請求資料的方法,第一種方法適用於簡單的驗證,表單驗證和業務邏輯放在一起,顯得業務程式碼臃腫,而且重複的驗證規則基本也是複製貼上,程式碼也不好看,這是關鍵。本篇教程就不說這個了,需要了解的請戳這裡。第二種就是建立請求驗證類,下面就詳細說

【laravel】 複雜單請求驗證,實現一個對應

一、序言 laravel 中提供了兩種驗證請求資料的方法,第一種方法適用於簡單的驗證,表單驗證和業務邏輯放在一起,顯得業務程式碼臃腫,而且重複的驗證規則基本也是複製貼上,程式碼也不好看,這是關鍵

Python 字典的值,即一個鍵對應

nbsp 多個 div 有一個 value 獲取 OS 是否 bsp #字典的一鍵多值 print‘方案一 list作為dict的值 值允許重復‘ d1={} key=1 value=2 d1.setdefault(key,[]).append(valu

例對一個或實體的驗證失敗。有關詳細信息,請參閱“EntityValidationErrors”屬性的解決

tro https span cep 實例 tps lte .data 防止 這個問題相信只要是做MVC的,都碰到過,也都知道錯誤的原因,就是觸發了定義的實例字段校驗規則。比如定義的不為空,但是為空了,或者定義的字段長度為50,但是超過50了。 可是有時雖然知道是這樣,

hql語句次比對查詢單字段

end nta 不能 ase color poll 存儲 pen ike 前端輸入客戶名稱,在使用hql查詢時,要同時比對表中,客戶名稱,客戶簡稱,拼音簡寫,客戶編碼等多個字段 hql寫法 String fdCustomerName=cv.poll("docMain.fdC

Flume採集個數據源對應channel,sink

Flume採集一個數據源對應多個channel,多個mysqlsink(自定義sink) a1.sources= r1 a1.channels= c1 a1.sinks= s1 s2 s3 # flume 1.6.0 #a1.sources.r1.type = exec #a1.s

使用JDBC次插入條記錄

程式碼如下: public static void insertBatch() { int count[]; int count1[]; Boolean isinsert = false; Connection con = null; PreparedS

oracle 用一個欄位更新另一個對應欄位

update wx_weather a set (a.high_l,a.low_l)= (select high_l, low_l from wx_original_weather b where a

004_015 Python 字典的值,即一個鍵對應

程式碼如下: #encoding=utf-8 print '中國' #字典的一鍵多值 print'方案一 list作為dict的值 值允許重複' d1={} key=1 value=2 d1.setdefault(key,[]).append(value) va

在JDBC次插入條記錄

{   con = getCon();   con.setAutoCommit(false);                                   // 需要用到事務,不能讓他自動提交,需要手動提交   pst = con.prepareStatement(INSERT_SQL);      

一個目標對應切面的例子

在之前的cglib代理原理中(至於cglib和jdk代理的區別,看之前的博文),我們涉及到了多個切面,但是那時候說的切面,還不算真正意義上的切面(沒有在spring配置檔案中配置)。現在我修改一個那個例子. 需求: 我們仍然查詢某一個人的薪水

oracle資料庫備份和恢復 怎樣將Oracle欄位更新到另中去

對於比較簡單的表,資料量不是特別多的表,可以使用簡單的sql語句來進行備份create table T_FA_Cat_20121207 as select * from T_FA_Cat 建立一個新表,把資料儲存起來 insert into  T_FA_Cat  sele

1.18 元件對映(一個對應

在實際程式設計中,一個數據庫表可以對應兩個類(例如husband和wife類,wife類是husband類的一個欄位。 一、annotation實現方式 1.wife類 public class wi

C++中個頭檔案可以對應原始檔

// one *.h file can correspond two or more *.cpp files // or a class definition can distribute in more than one *.cpp files // par

Oracle怎樣將欄位更新到另中去

Oracle中將一張表的多個欄位更新到另一張表中去 update t_retired_device a  set(a.tag_id, a.sub_tag_id) =  (select b.tag_id