java Hibernate - TypedQuery.getResultList() 返回相同对象的列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5352357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate - TypedQuery.getResultList() returns a list of the same object
提问by Francesco
Here is a more and maybe better description of the problem:
这是对问题的更多甚至更好的描述:
I do a simple select query. The returning list contains the exact number of records/objects as if I do the same query in the DB, but the problem is that all the objects are the same/identical.
我做了一个简单的选择查询。返回列表包含准确数量的记录/对象,就像我在数据库中执行相同的查询一样,但问题是所有对象都相同/相同。
For ex, this is the result in the DB (I removed the null values):
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
例如,这是数据库中的结果(我删除了空值):
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 瓦利塞恩
And this is the content of the variable addresses as I can see it in Eclipse during the debugging after the query has been executed:
这是我在 Eclipse 中在执行查询后调试期间可以看到的变量地址的内容:
addresses ArrayList (id=81)
elementData Object[10] (id=86)
[0] DLDBAddress (id=82)
[1] DLDBAddress (id=82)
[2] null
...
modCount 1
size 2
地址 ArrayList (id=81)
elementData Object[10] (id=86)
[0] DLDBAddress (id=82)
[1] DLDBAddress (id=82)
[2] null
...
modCount 1
size 2
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]
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]
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]]
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]]
As you can see, the two objects are identical. They shoul instead differ from the addressNr and addressType...
如您所见,这两个对象是相同的。它们应该与 addressNr 和 addressType 不同......
This is the piece of code where I build up the query:
这是我构建查询的代码段:
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();
}
and this is the (quite simple) resulting query:
这是(非常简单)结果查询:
from ch.ethz.id.wai.pdb.bo.DLDBAddress s where s.persid = 26801
来自 ch.ethz.id.wai.pdb.bo.DLDBAddress s 其中 s.persid = 26801
This is the generated query:
这是生成的查询:
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
And here the entity:
这里是实体:
@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;
...
Am I missing something?
我错过了什么吗?
Ah, I'm connecting to an Oracle DB.
啊,我正在连接到 Oracle DB。
Thanks in advance Francesco
在此先感谢弗朗西斯科
回答by Vladimir Dyuzhev
where dldbaddres0_.PERSID=26801
@Id
@Column(name = "PERSID", insertable = false, updatable = false)
You defined PERSID as @Id, which is a primary key. Is it really unique for your application? From the behavior it is not. But for Hib it MUST be.
您将 PERSID 定义为 @Id,它是一个主键。它对您的应用来说真的是独一无二的吗?从行为上看不是。但对于 Hib 来说,它必须是。
So what happens:
那么会发生什么:
- You have two+ records in the database with PERSID = 26801
- You query them WHERE PERSID=26801
- SQL Query returns two+ rows
- Hib loads first one, and puts into session, with PERSID as a key (because it is marked as @Id). Object is placed into the result list.
- Hib loads second one, notices that an object with same @Id is already in the session, and just places the reference into the result List. Row data are ignored.
- Thus you get two+ copies.
- 您在数据库中有两条以上的记录,PERSID = 26801
- 你查询他们 WHERE PERSID=26801
- SQL 查询返回两行以上
- Hib 加载第一个,并进入会话,以 PERSID 作为键(因为它被标记为 @Id)。对象被放入结果列表。
- Hib 加载第二个,注意到会话中已经有一个具有相同@Id 的对象,然后将引用放入结果列表中。行数据被忽略。
- 因此你会得到两个以上的副本。