Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 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: 1433
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.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


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: 1433
You need to add the data access code as well, and the logged SQL statements.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


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: 1433
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.

_________________
If you liked my answer, you are going to love my High-Performance Java Persistence book and my blog as well.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 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.