java - JPA - EclipseLink make additional SELECT requests for relationships when merging an entity -


i've got question on "strange" behaviour when updating entity merge method.

i have entity "personne" have 2 relationship (fetch = lazy). have html form use modify fields of entity. when saving entity merge method, see select requests relationships.

i don't understand why these selects done , avoid them because data loaded behaviour can "huge".

there entity :

@entity @table(name="personne") @namedquery(name="personne.findall", query="select p personne p") public class personne implements serializable {  @id @generatedvalue(strategy=generationtype.identity) @column(unique=true, nullable=false) private integer id;  @temporal(temporaltype.timestamp) @column(name="date_naissance") private date datenaissance;  @column(length=75) private string denomination;  @column(length=75) private string nom;  @column(precision=10, scale=2) private bigdecimal poids;  @column(length=75) private string prenom;  @column(precision=10, scale=2) private bigdecimal taille;  //bi-directional many-to-one association contact @onetomany(mappedby="personne", fetch = fetchtype.lazy) private list<contact> contacts;  //bi-directional many-to-one association log @onetomany(mappedby="personne", fetch = fetchtype.lazy) private list<logs> logs;  //bi-directional many-to-one association personnehasadresse @onetomany(mappedby="personne", fetch = fetchtype.lazy) private list<personnehasadresse> personnehasadresses;  //bi-directional many-to-one association personnehaspersonne @onetomany(mappedby="parent", fetch = fetchtype.lazy) private list<personnehaspersonne> personnehaspersonnesparent;  //bi-directional many-to-one association personnehaspersonne @onetomany(mappedby="child", fetch = fetchtype.lazy) private list<personnehaspersonne> personnehaspersonneschild;  public personne() { }  public integer getid() {     return this.id; }  public void setid(integer id) {     this.id = id; }  public date getdatenaissance() {     return this.datenaissance; }  public void setdatenaissance(date datenaissance) {     this.datenaissance = datenaissance; }  public string getdenomination() {     return this.denomination; }  public void setdenomination(string denomination) {     this.denomination = denomination; }  public string getnom() {     return this.nom; }  public void setnom(string nom) {     this.nom = nom; }  public bigdecimal getpoids() {     return this.poids; }  public void setpoids(bigdecimal poids) {     this.poids = poids; }  public string getprenom() {     return this.prenom; }  public void setprenom(string prenom) {     this.prenom = prenom; }  public bigdecimal gettaille() {     return this.taille; }  public void settaille(bigdecimal taille) {     this.taille = taille; }  @jsonignore public list<contact> getcontacts() {     return this.contacts; }  public void setcontacts(list<contact> contacts) {     this.contacts = contacts; }  public contact addcontact(contact contact) {     this.getcontacts().add(contact);     contact.setpersonne(this);      return contact; }  public contact removecontact(contact contact) {     this.getcontacts().remove(contact);     contact.setpersonne(null);      return contact; }  @jsonignore public list<logs> getlogs() {     return this.logs; }  public void setlogs(list<logs> logs) {     this.logs = logs; }  public logs addlog(logs log) {     this.getlogs().add(log);     log.setpersonne(this);      return log; }  public logs removelog(logs log) {     this.getlogs().remove(log);     log.setpersonne(null);      return log; }  @jsonignore public list<personnehasadresse> getpersonnehasadresses() {     return this.personnehasadresses; }  public void setpersonnehasadresses(list<personnehasadresse> personnehasadresses) {     this.personnehasadresses = personnehasadresses; }  @jsonignore public personnehasadresse addpersonnehasadress(personnehasadresse personnehasadress) {     this.getpersonnehasadresses().add(personnehasadress);     personnehasadress.setpersonne(this);      return personnehasadress; }  public personnehasadresse removepersonnehasadress(personnehasadresse personnehasadress) {     this.getpersonnehasadresses().remove(personnehasadress);     personnehasadress.setpersonne(null);      return personnehasadress; }  @jsonignore public list<personnehaspersonne> getpersonnehaspersonnesparent() {     return this.personnehaspersonnesparent; }  public void setpersonnehaspersonnesparent(list<personnehaspersonne> personnehaspersonnesparent) {     this.personnehaspersonnesparent = personnehaspersonnesparent; }  public personnehaspersonne addpersonnehaspersonnesparent(personnehaspersonne personnehaspersonnesparent) {     this.getpersonnehaspersonnesparent().add(personnehaspersonnesparent);     personnehaspersonnesparent.setparent(this);      return personnehaspersonnesparent; }  public personnehaspersonne removepersonnehaspersonnesparent(personnehaspersonne personnehaspersonnesparent) {     this.getpersonnehaspersonnesparent().remove(personnehaspersonnesparent);     personnehaspersonnesparent.setparent(null);      return personnehaspersonnesparent; }  @jsonignore public list<personnehaspersonne> getpersonnehaspersonneschild() {     return this.personnehaspersonneschild; }  public void setpersonnehaspersonneschild(list<personnehaspersonne> personnehaspersonneschild) {     this.personnehaspersonneschild = personnehaspersonneschild; }  public personnehaspersonne addpersonnehaspersonneschild(personnehaspersonne personnehaspersonneschild) {     this.getpersonnehaspersonneschild().add(personnehaspersonneschild);     personnehaspersonneschild.setchild(this);      return personnehaspersonneschild; }  public personnehaspersonne removepersonnehaspersonneschild(personnehaspersonne personnehaspersonneschild) {     this.getpersonnehaspersonneschild().remove(personnehaspersonneschild);     personnehaspersonneschild.setchild(null);      return personnehaspersonneschild; } 

and generic method update object :

public void merge(e obj) {         entitymanager em = persitencemanager.getinstance().getem(this.persistunit);         try {             entitytransaction t = em.gettransaction();              try {                 t.begin();                 em.merge(obj);                 t.commit();             } {                 if (t.isactive()) {                     t.rollback();                 }             }         } {             em.close();         }     } 

before update statement, there selects contacts , logs. know why ? normal behaviour ? if yes, how avoid ?

thanks !


edit 1:

the complete code layers (from rest dao):

@path("personnes") @produces({ mediatype.application_json }) @consumes({ mediatype.application_json }) public class personnesrest {      private personneservices personneservices = new personneservices();      ...      @put     @path("{id}")     public response update(@pathparam("id") integer id, personne personne) {         if (personne == null || !id.equals(personne.getid())) {             return response.status(status.bad_request).build();         }          this.personneservices.merge(personne);         return response.nocontent().build();     }      @post     public response create(personne personne) {         personne createdpersonne = this.personneservices.persist(personne);         return response.created(uri.create("personnes/" + createdpersonne.getid())).build();     }      ...  }  public class personneservices extends abstractbasicservices<personne> {      public personneservices() {         super(new personnedao(), personne.class, "poi.model");     } }  public class personnedao extends abstractbasicdao<personne> {  }  public abstract class abstractbasicservices<e> {      private abstractbasicdao<e> dao;      private class<e> clazz;      private string persistunit;      public abstractbasicservices(abstractbasicdao<e> dao, class<e> clazz, string persistunit) {         this.dao = dao;         this.clazz = clazz;         this.persistunit = persistunit;     }   public e persist(e obj) {         entitymanager em = persitencemanager.getinstance().getem(this.persistunit);         e res = null;          try {             entitytransaction t = em.gettransaction();             try {                 t.begin();                 res = this.dao.persist(obj, em);                 t.commit();             } {                 if (t.isactive()) {                     t.rollback();                 }             }         } {             em.close();         }          return res;     }  // merge method 1 in first post.  }  public abstract class abstractbasicdao<t> {     public t persist(t obj, entitymanager em) {         em.persist(obj);         em.flush();         em.refresh(obj);         return obj;     }      public t merge(t obj, entitymanager em) {         return em.merge(obj);     } } 

edit 2:

after review, had (in persistence.xml) "shared cache mode" "none". obvious entity manager need reload relationships (silly me...). set "default".

i made following tests (i reboot server each test) :

  • (test 1-1) create new entity (persist): insert + selects relationships.
  • (test 1-2) update previous entity (merge): update (no select).
  • (test 2-1) update entity (merge): update + selects relationships.
  • (test 2-2) update same entity (merge): update (no select).

does seem normal ?


edit 3:

i posted entire personne entity , see mistake. put @jsonignore avoid loading of relationships when querying display list of personne attributes because of marshalling of relationships. unmarshalling did not set indirected lists. removed annotations.

i created wrapper contains attributes need jax-rs layer , update fields corresponding entity when need update , there no more additional select.

thanks time.

i cannot reproduce this.

can verify right before calling merge() whether following expression returns false:

((org.eclipse.persistence.indirection.indirectcontainer)obj.getcontacts()).isinstantiated() 

(assuming have getter named getcontacts() returns field contacts within entity class).

if returns false "strange" behavior needs further investigated.

if returns true (which case) lazy loaded collection has been accessed before hence eclipselink needs check whether has changed in database.
in case, check code accesses collection beforehand (use breakpoint figure out).


Comments

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -