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

11,917
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.
Share:
11,917
Francesco
Author by

Francesco

Updated on June 30, 2022

Comments

  • Francesco
    Francesco almost 2 years

    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