-->
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.  [ 7 posts ] 
Author Message
 Post subject: Unidirectional ManyToMany not saved for some reason
PostPosted: Wed Sep 06, 2017 4:44 pm 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
Hi, I broke my head, I can figure out what do I do wrong.

I have two entities with unidirectional ManyToMany relation.
Command has many jobs.
Job doesn't know anything about Command.
Same job can belong to different commands.

I can save single Job.
I can save single Command (w/o jobs)
Command with job is not saved correctly.
Command table gets record.
Reference doesn't get record.
Job table gets record.

here is code
Code:
@Entity
@DynamicInsert
@DynamicUpdate
@SelectBeforeUpdate
@Table
class Job extends AbstractEntity {
// some regular fields go here.
}

@Entity
@DynamicInsert
@DynamicUpdate
@SelectBeforeUpdate
@Table
class Command extends AbstractEntity {
 
  // some regular fields go here.

  @ManyToMany(fetch = FetchType.EAGER, cascade = Array(CascadeType.ALL))
  @JoinTable(name = "CommandJobs",
    joinColumns = Array(new JoinColumn(name = "CommandId", nullable = false)),
    inverseJoinColumns = Array(new JoinColumn(name = "JobId", nullable = false)))
  var jobs: java.util.Set[Job] = _

  def addJobs(job: Job): Unit = {
    if (jobs == null) {
      jobs = new util.HashSet[Job]()
    }

    jobs.add(job)
  }
}


I try to persist command and I see that Hibernate does three SQL queries (SQL debug enabled):
1. insert into Command
2. Insert into Job

Where is insert into CommandJobs?


Top
 Profile  
 
 Post subject: Re: Unidirectional ManyToMany not saved for some reason
PostPosted: Wed Sep 06, 2017 6:32 pm 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
I've changed ManyToMany to
Code:
  @OneToMany(fetch = FetchType.EAGER, cascade = Array(CascadeType.PERSIST, CascadeType.MERGE))


Didn't help, same effect.


Top
 Profile  
 
 Post subject: Re: Unidirectional ManyToMany not saved for some reason
PostPosted: Thu Sep 07, 2017 1:05 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
We have a similar example in Hibernate and it works like a charm.

Now, although unrelated to your issue there are 3 things to consider:

1. It makes no sense to use a null collection reference. It's always better to just initialize it to a new ArrayList or HashSet and free your code from null checks.
2. Using EAGER is bad for performance.
3. Using CascadeType.ALL means that you inherit CascaadeType.REMOVE which is bad for @ManyToMany.

So, try isolating it with our test case templates, and you'll surely find what you did wrong. You can also debug the test I mentioned on the GitHub repository and compare with yours to see where they differ.


Top
 Profile  
 
 Post subject: Re: Unidirectional ManyToMany not saved for some reason
PostPosted: Thu Sep 07, 2017 6:10 am 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
Hi, thanks for your input. I've simplified my relation. Now I'm using unidirectional OneToMany with JoinTable.
Command has many Jobs. Relation between Command and Job stored in separate table: CommandJobs
Code:
@Entity
@DynamicInsert
@DynamicUpdate
@SelectBeforeUpdate
@Table
class Job extends AbstractEntity {
// some regular fields go here.
}

@Entity
@DynamicInsert
@DynamicUpdate
@SelectBeforeUpdate
@Table
class Command extends AbstractEntity {
 
  // some regular fields go here.

  @OneToMany(fetch = FetchType.EAGER, cascade = Array(CascadeType.ALL))
  @JoinTable(name = "CommandJobs",
    joinColumns = Array(new JoinColumn(name = "CommandId", nullable = false)),
    inverseJoinColumns = Array(new JoinColumn(name = "JobId", nullable = false)))
  var jobs: java.util.Set[Job] = _

  def addJobs(job: Job): Unit = {
    if (jobs == null) {
      jobs = new util.HashSet[Job]()
    }

    jobs.add(job)
  }
}


It didn't affect outcome. Command created, Job created, but CommandJobs in not updated with reference between Command and Job


Top
 Profile  
 
 Post subject: Re: Unidirectional ManyToMany not saved for some reason
PostPosted: Thu Sep 07, 2017 8:18 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
You need to add the data access code as well, and the logged SQL statements.


Top
 Profile  
 
 Post subject: Re: Unidirectional ManyToMany not saved for some reason
PostPosted: Sun Sep 10, 2017 5:07 pm 
Newbie

Joined: Mon Jul 03, 2017 6:40 am
Posts: 10
So, we found the problem. Lower DAO level was calling
persist + refresh. I need to call refresh, since createdAt, updatedAt fields are driven by DB triggers. Refresh was causing problem. The idea is:
transaction started
job1 saved
job1 refreshed

command1 saved
command1 refreshed
current "state" of command entity is overwritten with DB state. DB knows nothing about job1, job2 and command1 relation yet.

Transaction committed.
Two jobs saved
One command saved.
job table is not populated since reference between command and jobs were lost because of refresh.

Does it seem to be correct explanation?


Top
 Profile  
 
 Post subject: Re: Unidirectional ManyToMany not saved for some reason
PostPosted: Mon Sep 11, 2017 1:06 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Why don't you save the Command and cascade to Jobs.

Then, you just need to flush and call refresh afterwards which can also cascade from Command to Jobs.


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

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.