Hibernate - TypedQuery.getResultList()返回同一对象的列表

Fra*_*sco 6 java hibernate jpa criteria

以下是对问题的更多和更好的描述:

我做一个简单的选择查询.返回列表包含确切的记录/对象数,就像我在数据库中执行相同的查询一样,但问题是所有对象都相同/相同.

例如,这是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 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]]

如您所见,这两个对象是相同的.他们应该与addressNr和addressType不同......

这是构建查询的代码段:

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();
}
Run Code Online (Sandbox Code Playgroud)

这是(非常简单)结果查询:

来自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
Run Code Online (Sandbox Code Playgroud)

在这里实体:

@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;

...
Run Code Online (Sandbox Code Playgroud)

我错过了什么吗?

啊,我正在连接到Oracle DB.

在此先感谢Francesco

Vla*_*hev 18

where dldbaddres0_.PERSID=26801

@Id
  @Column(name = "PERSID", insertable = false, updatable = false)
Run Code Online (Sandbox Code Playgroud)

您将PERSID定义为@Id,这是一个主键.它对您的应用来说真的很独特吗?从行为来看并非如此.但对于Hib来说,它必须是.

那么会发生什么:

  1. 数据库中有两条+记录,PERSID = 26801
  2. 您查询它们WHERE PERSID = 26801
  3. SQL Query返回两个+行
  4. Hib加载第一个,并进入会话,PERSID作为键(因为它标记为@Id).对象放入结果列表中.
  5. Hib加载第二个,注意到具有相同@Id的对象已经在会话中,并且只是将引用放入结果列表中.行数据被忽略.
  6. 因此你得到两个+副本.