【问题标题】:Hibernate - TypedQuery.getResultList() returns a list of the same objectHibernate - TypedQuery.getResultList() 返回相同对象的列表
【发布时间】:2011-07-18 03:57:09
【问题描述】:

下面是对问题的更多,也许更好的描述:

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

例如,这是数据库中的结果(我删除了空值):
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、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();
}

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

来自 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 数据库。

提前致谢 弗朗切斯科

【问题讨论】:

  • 1.与 CriteriaBuilder 相比,我更有可能使用 hql,因为查询更易于阅读。 2. 没有看到传递给方法的 where 子句,很难告诉你哪里出了问题。
  • 根据我的经验,使用 JPA 和 Hibernate EntityManager,当 id 不是真正唯一时会发生这种情况,这在 JPA 中是强制性的。 Hibernate EntityManager 完全实现了 JPA 2,因此这里也应该适用。你也会发布你的实体吗?
  • Hibernate 生成的实际 SQL 是什么?更改您的 Hibernate 配置以显示该信息。这可能会更好地解释问题所在。
  • 埃里克你是对的。在我的课堂上,我将 persid 设置为 @Id,但它不是唯一的。我定义了一个复合 ID,现在它可以工作了!非常感谢。
  • 呃。发布的答案没有注意到您在评论中提到问题已解决。无论如何,我的回答可能有助于解释 Hib 的行为。

标签: java hibernate jpa criteria


【解决方案1】:
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. 因此,您可以获得两份以上的副本。

【讨论】:

    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多