2011-03-18 118 views
6

名單這是問題的一個更,也許更好的描述:休眠 - TypedQuery.getResultList()返回相同的對象

我做一個簡單的選擇查詢。返回列表包含記錄/對象的確切數量,就像我在數據庫中執行相同的查詢一樣,但問題是所有對象都是相同/相同的。

例如,這是DB中的結果(我刪除了空值):
26801 01-JAN-00 7 31-DEC-99 7 Obere Kirchstr。 26 CH 8304 Walliselln
26801 01-JAN-00 2 31-DEC-99 2 Obere Kirchstr。 26 CH 8304 Walliselln

這是可變的地址的內容作爲我可以在調試期間看到它在Eclipse查詢已被執行之後:

地址的ArrayList(ID = 81)
elementData中對象[ 10](ID = 86)
[0] DLDBAddress(ID = 82)
[1] DLDBAddress(ID = 82)
[2]空
...
modCount的1
大小2

DLDBAddress [persid = 26801,valPeriodStart = 1900-01-01,valPeriodEnd = 9999-12-31,addressNr = 7,addressType = 7,addressRow1 = null,addressRow2 = Obere Kirchstr。 26,addressRow3 = NULL,國家= CH,POSTALCODE = 8304,城市= Walliselln,phoneNr = NULL,faxNr = NULL,sekretaryPhoneNr = NULL,alternatPhoneNr = NULL,pagerNr =空]

DLDBAddress [persid = 26801,valPeriodStart = 1900-01-01,valPeriodEnd = 9999-12-31,addressNr = 7,addressType = 7,addressRow1 = null,addressRow2 = Obere Kirchstr。 26,addressRow3 = null,country = CH,postalCode = 8304,city = Walliselln,phoneNr = null,faxNr = null,sekretaryPhoneNr = null,alternatPhoneNr = null,pagerNr = null]]

正如你所看到的,對象是相同的。他們建議立即進行刪除,而不是從addressNr和地址類型不同...

這是一段代碼,我建立查詢:

public static <T> List<T> findBy(EntityManager eM, Class<T> boClass, String whereClause, String whereValue) 
{ 
    EntityManager entityManager = eM; 
    Query query = entityManager.createQuery("from " + boClass.getName() + " s where s." + whereClause + " = " + whereValue); 
    ... 
    return (List<T>) query.getResultList(); 
} 

,這是(很簡單)結果查詢:

從ch.ethz.id.wai.pdb.bo.DLDBAddress S其中s.persid = 26801

這是產生的查詢:

Hibernate: 
select 
dldbaddres0_.PERSID as PERSID0_, 
dldbaddres0_.ADRNUM as ADRNUM0_, 
dldbaddres0_.ADRZEIL1 as ADRZEIL3_0_, 
dldbaddres0_.ADRZEIL2 as ADRZEIL4_0_, 
dldbaddres0_.ADRZEIL3 as ADRZEIL5_0_, 
dldbaddres0_.ADRTYP as ADRTYP0_, 
dldbaddres0_.ADRAUSWTEL as ADRAUSWTEL0_, 
dldbaddres0_.ADRORT as ADRORT0_, 
dldbaddres0_.ADRLAND as ADRLAND0_, 
dldbaddres0_.ADRFAX as ADRFAX0_, 
dldbaddres0_.ADRPSA as ADRPSA0_, 
dldbaddres0_.ADRTEL as ADRTEL0_, 
dldbaddres0_.ADRPLZ as ADRPLZ0_, 
dldbaddres0_.ADRSEKTEL as ADRSEKTEL0_, 
dldbaddres0_.BISDAT as BISDAT0_, 
dldbaddres0_.VONDAT as VONDAT0_ 
from 
NETHZ.V_DLDB_ADRESSE dldbaddres0_ 
where 
dldbaddres0_.PERSID=26801 

這裏的實體:

@Entity 
@Table(name = "V_DLDB_ADRESSE", schema="NETHZ") 
public class DLDBAddress 
{ 
    @Id 
    @Column(name = "PERSID", insertable = false, updatable = false) 
    private Integer persid; 
    @Temporal(TemporalType.DATE) 
    @Column(name = "VONDAT", insertable = false, updatable = false) 
    private Date valPeriodStart; 
    @Temporal(TemporalType.DATE) 
    @Column(name = "BISDAT", insertable = false, updatable = false) 
    private Date valPeriodEnd; 
    @Column(name = "ADRNUM", insertable = false, updatable = false) 
    private Integer addressNr; 
    @Column(name = "ADRTYP", insertable = false, updatable = false) 
    private Integer addressType; 
    @Column(name = "ADRZEIL1", insertable = false, updatable = false) 
    private String addressRow1; 
    @Column(name = "ADRZEIL2", insertable = false, updatable = false) 
    private String addressRow2; 
    @Column(name = "ADRZEIL3", insertable = false, updatable = false) 
    private String addressRow3; 
    @Column(name = "ADRLAND", insertable = false, updatable = false) 
    private String country; 
    @Column(name = "ADRPLZ", insertable = false, updatable = false) 
    private String postalCode; 
    @Column(name = "ADRORT", insertable = false, updatable = false) 
    private String city; 
    @Column(name = "ADRTEL", insertable = false, updatable = false) 
    private String phoneNr; 
    @Column(name = "ADRFAX", insertable = false, updatable = false) 
    private String faxNr; 
    @Column(name = "ADRSEKTEL", insertable = false, updatable = false) 
    private String secretaryPhoneNr; 
    @Column(name = "ADRAUSWTEL", insertable = false, updatable = false) 
    private String alternatPhoneNr; 
    @Column(name = "ADRPSA", insertable = false, updatable = false) 
    private String pagerNr; 

... 

我這麼想嗎?

啊,我連接到一個Oracle數據庫。

預先感謝 弗朗西斯

+0

1.我更願意使用hql而不是CriteriaBuilder,因爲查詢更容易閱讀。 2.沒有看到傳遞給方法的where子句,很難告訴你什麼是錯的。 – Speck 2011-03-18 13:23:46

+1

根據我的經驗,使用JPA和Hibernate EntityManager時,會發生這種情況,因爲id不是唯一的,這在JPA中是必需的。 Hibernate EntityManager完全實現了JPA 2,所以在這裏也應該適用。你會發布你的實體嗎? – Erik 2011-03-18 13:24:46

+1

什麼是由Hibernate生成的實際SQL?改變你的Hibernate配置來顯示這些信息。這可能會提供一個更好的解釋,說明發生了什麼問題。 – 2011-03-18 13:26:30

回答

16
where dldbaddres0_.PERSID=26801 

@Id 
    @Column(name = "PERSID", insertable = false, updatable = false) 

你定義PERSID爲@Id,這是一個主鍵。它對你的應用程序來說真的很獨特嗎從行爲不是。但對於Hib它必須是。

所以會發生什麼:

  1. 您在PERSID = 26801
  2. 數據庫有兩個+記錄您對它們進行查詢的WHERE PERSID = 26801
  3. SQL查詢返回兩個+行
  4. 的Hib負荷第一個,並將PERSID作爲關鍵字(因爲它被標記爲@Id)進入會話。對象被放置在結果列表中。
  5. Hib加載第二個,注意到具有相同@Id的對象已經在會話中,並將引用放入結果列表中。行數據被忽略。
  6. 因此,你得到兩個+副本。
+0

優秀的答案。很好的解釋。 +1分6分。 – OO7 2015-12-02 05:20:45