-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Trouble to keep db and java entity's state in sync
PostPosted: Mon Jul 21, 2014 5:46 pm 
Newbie

Joined: Thu Dec 13, 2012 5:12 pm
Posts: 2
Hello guys,

I have some trouble with Hibernate (v3.6.10).

I use the following mapping :
Code:
@Entity(name = "team.Candidacy")
@Table(schema = "team")
public class Candidacy {
    @ManyToOne(optional = false)
    @ForeignKey(name = "fk_candidacy_team")
    private Team team;
}

@Entity(name = "team.Team")
@Table(schema = "team")
public class Team {
    @OneToMany(mappedBy = "team")
    @OnDelete(action = OnDeleteAction.CASCADE)
    private final Collection<Candidacy> candidacies = new LinkedList<>();
}


When I want to create a new candidacy, I use the current code :
Code:
public class CandidacyDao {
    public Candidacy apply(Team team) {
        Candidacy candidacy = new Candidacy();
        candidacy.setTeam(team);
        team.getCandidacies().add(candidacy);
        getCurrentSession().save(candidacy);
        return candidacy;
    }
}


But this code doesn't work in all case.
This test case don't works :
Code:
@Test
public void testFail() {
   final Team team = this.teamDao.get(1); // team created from dbunit
   final Candidacy candidacy = this.apply(team);
   assertThat(team.getCandidacies()).hasSize(1).contains(candidacy);
   // java.lang.AssertionError: expected size:<1> but was:<2> for <[Candidacy@70dc0648, Candidacy@70dc0648]>
}

Note the duplicated candidacy on the list at the end.

After a (lot of) debug, I understand why :
Code:
public class org.hibernate.collection.PersistentBag {
   public boolean add(Object object) {
      if ( !isOperationQueueEnabled() ) {
         write();
         return bag.add(object);
      } else {
         queueOperation( new SimpleAdd(object) );
         return true;
      }
   }

   protected boolean isOperationQueueEnabled() {
      return !initialized && isConnectedToSession() && isInverseCollection();
   }
}

So, « team.getCandidacies() » is not previously resolved (lazy-loaded) before the « .add(candidacy) », and even this « .add » doesn't trigger the resolution (write access) and postpone it when the « .getCandidacies() » will be really read (on « assert »).
At « assert » time, the children are really resolved, so a SELECT is done in database, fetch all the candidacies including the newly created, and realize the real addition, leading to a duplicated one.

If I force the « .getCandidacies() » or create directly the team from the test, all is good :
Code:
@Test
public void testSuccess1() {
   final Team team = this.teamDao.get(1);
   this.logger.debug("{}", team.getCandidacies()); // force the read
   final Candidacy candidacy = this.apply(team);
   assertThat(team.getCandidacies()).hasSize(1).contains(candidacy);
}

@Test
public void testSuccess2() {
   final Team team = new Team();
   getCurrentSession().save(team); // native initialization
   final Candidacy candidacy = this.apply(team);
   assertThat(team.getCandidacies()).hasSize(1).contains(candidacy);
}


If I remove the « .add » on the DAO, the behaviour is the opposite :
If lazy-loaded before the « .apply », failure at the end because the candidacy is not in the list of the team.
If not, test success because the « assert » will trigger the resolution, but with no « .add » this time so no duplicate and correct list (fetch from db).

So, my question is : how I can keep in sync the database and the java entity state in case of children and reverse relation, in any case (previously lazy-loaded or not) ? :'(

Thanks in advance.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.