hibernate - Java JPA Unit Test saving 2 items -


i have simple @onetomany setup 2 entities - item , group, , having interesting problem. when integration test creates group, adds item , saves group, 2 instances of item end getting saved. ideas why? i'm using hibernate, if matters:

the item entity

@entity public class namedentity implements java.io.serializable {     long             id;      @notnull     string           name;      namedentitygroup namedentitygroup;      namedentitytype  type;      @enumerated(enumtype.string)     public namedentitytype gettype() { return type; }      @id     @generatedvalue     public long getid() { return id; }      public string getname() { return name; }      @joincolumn(name = "namedentitygroupid")     @jsonbackreference     @manytoone(cascade = { cascadetype.all }, fetch = fetchtype.eager)     public namedentitygroup getnamedentitygroup() { return  this.namedentitygroup; } } 

the group entity

    @entity     public class namedentitygroup implements serializable {         long              id;          string            name;          list<namedentity> namedentities;          @id         @generatedvalue         public long getid() { return this.id; }          public string getname() { return this.name; }          @jsonmanagedreference         @onetomany(cascade = { cascadetype.all }, mappedby = "namedentitygroup", fetch = fetchtype.eager)         public list<namedentity> getnamedentities() { return this.namedentities; }          public void addnamedentity(namedentity ne) {             if (this.namedentities == null) {                 this.namedentities = new arraylist<namedentity>();             }             if (!namedentities.contains(ne)) {                 this.namedentities.add(ne);             }             ne.setneg(this);         }     } 

the dao class

    public void save(namedentity ne) throws entityvalidationexception {         validate(ne);         if(ne.getnamedentitygroup() != null) {             if(!em.contains(ne.getnamedentitygroup())) {                 ne.setnamedentitygroup(em.merge(ne.getnamedentitygroup()));                 em.persist(ne);                 return;             }         }           em.persist(ne);      } 

the test method

    @test     public void testaddnamedentitytoexistinggroup() throws entityvalidationexception {         int nesize = ed.getallnamedentities().size();         namedentitygroup neg = ed.getallnamedentitygroups().iterator().next();          assertnotnull(neg);         asserttrue(neg.getnamedentities().size() == 0);         em.detach(neg);          namedentity n = new namedentity();         n.setname("hello");          neg.addnamedentity(n);         n.setnamedentitygroup(neg);          n.settype(namedentitytype.default);          ed.save(n);         for(namedentity e : ed.getallnamedentities()) {             l.error("entity: {}", e);         }          asserttrue("size " + ed.getallnamedentities().size() + " should " + (nesize + 1) + " group has "                 + neg.getnamedentities().size() + " entities (should 1) " + ed.getallnamedentities(), nesize + 1 == ed.getallnamedentities().size());     } 

here output:

entity: namedentity [id=1, name=super mario brothers, namedentitygroup=null, type=null] entity: namedentity [id=3, name=mario kart, namedentitygroup=null, type=null] entity: namedentity [id=5, name=f-zero, namedentitygroup=null, type=null] entity: namedentity [id=7, name=hello, namedentitygroup=namedentitygroup [id=2, name=super mario brothers, count(entity)=1], type=default] entity: namedentity [id=8, name=hello, namedentitygroup=namedentitygroup [id=2, name=super mario brothers, count(entity)=1], type=default] 

id's 7 , 8 duplicates in output save method inserting item 2 times.

your dao save method ugly, refactor it, otherwise expect more issues one. :)

the issue in em.merge(ne.getnamedentitygroup()) in dao save method. because namedentitygroup cascades all namedentities, merge cascaded ne transient (unsaved), causing new namedentity instance created. ne instance removed namedentities collection , copy of placed in it. session.merge javadoc:

copy state of given object onto persistent object same identifier. if there no persistent instance associated session, loaded. return persistent instance. if given instance unsaved, save copy of , return newly persistent instance. given instance not become associated session. operation cascades associated instances if association mapped cascade="merge".

afterwards persist passed in ne well, end 2 persisted namedentity instances: 1 created (copied) merge , 1 explicitly persisted (ne).

the proper solution refactor save not contain code if(!em.contains(ne.getnamedentitygroup())) , similar things.

the ugly quick fix remove unnecessary em.persist(ne) if body. make things work, confusing (the passed in ne still transient after save returns).

a little better quick fix load persistent namedentitygroup:

namedentitygroup group = em.getreference(namedentitygroup.class, ne.getnamedentitygroup().getid()); ne.setnamedentitygroup(group); 

Comments

Popular posts from this blog

Fail to load namespace Spring Security http://www.springframework.org/security/tags -

sql - MySQL query optimization using coalesce -

unity3d - Unity local avoidance in user created world -