Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate - TypedQuery.getResultList() returns a list of the same object

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

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:

addresses 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]]

As you can see, the two objects are identical. They shoul instead differ from the addressNr and 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

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.

Thanks in advance Francesco

like image 498
Francesco Avatar asked Mar 18 '11 13:03

Francesco


People also ask

Does query getResultList return null?

getResultList() returns an empty list instead of null . So check isEmpty() in the returned result, and continue with the rest of the logic if it is false. Save this answer.

How do I persist a list in JPA?

Since JPA 2.0, you can use an element collection to persist a Collection of value types. You just need to annotate the attribute with @ElementCollection and the persistence provider will persist the elements of the Collection in an additional database table.

How fetch all records from a table in hibernate?

JPQL provides a simple and straightforward way to get all entities from a table. Our Hibernate session's createQuery() method receives a typed query string as the first argument and the entity's type as the second. We execute the query with a call to the getResultList() method which returns the results as a typed List.

What is typed query in hibernate?

TypedQuery gives you an option to mention the type of entity when you create a query and therefore any operation thereafter does not need an explicit cast to the intended type. Whereas the normal Query API does not return the exact type of Object you expect and you need to cast.


1 Answers

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.

So what happens:

  1. You have two+ records in the database with PERSID = 26801
  2. You query them WHERE PERSID=26801
  3. SQL Query returns two+ rows
  4. 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.
  5. 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.
  6. Thus you get two+ copies.
like image 108
Vladimir Dyuzhev Avatar answered Nov 15 '22 06:11

Vladimir Dyuzhev