I have 3 entities: job, schedule and groups, the relationship between them are: schedule has multiple groups, and multiple jobs; job has multiple groups, which may or may not get from the schedule it related to
when I created a schedule, i specified its groups, then i created a job, whose schedule is the one just created, and the job's group is the groups from that schedule, and then I got this error message of "detached entity passed to persist". I tried to update the cascade type to all kind of combination but still won't work. please help.
here is my code:
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "groups")
public class Group {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "group_guid", nullable = false, unique = true)
private String groupId;
}
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "schedules")
public class Schedule {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
....
@ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
@JoinTable(name = "schedules_to_groups",
joinColumns = @JoinColumn(name = "schedule_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name="group_id", referencedColumnName = "id"))
private List<Group> groups;
@OneToMany(mappedBy = "schedule", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private Set<Job> job;
....
@Entity
@Getter
@Setter
@NoArgsConstructor
@Table(name = "jobs")
public class Job {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "jobs_to_groups",
joinColumns = @JoinColumn(name = "job_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name="group_id", referencedColumnName = "id"))
private List<Group> groups;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "schedule_fk")
private Schedule schedule;
the code to create job:
List<Schedule> scheduleList = scheduleRepository.findAll();
for (Schedule schedule : scheduleList) {
Job job = new Job();
job.setSchedule(schedule);
job.setGroups(schedule.getGroups()); <--- get it from schedule
jobRepository.save(job);
...
}
error message i got:
org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.xxx.Group
I tried to remove 'cascade = CascadeType.ALL' from Job class, the above code pass , however the following code failed:
Group group6 = new Group();
group6.setGroupId("group6");
Job job = new Job();
job.setGroups(Lists.newArrayList(group6));
jobRepository.save(job); <--- failed here
the error message is:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.xxx.ReportGroup
Last I tried 'cascade = CascadeType.MERGE' in Job on groups field, i saw an even strange behavior, originally schedule has 3 groups, after the following code, the relationship between schedule and 3 groups was removed, instead job has relationship with those 3 groups, but what I expect is both schedule and job have those 3 groups.
List<Schedule> scheduleList = scheduleRepository.findAll();
for (Schedule schedule : scheduleList) {
Job job = new Job();
job.setSchedule(schedule);
job.setGroups(schedule.getGroups()); <--- get it from schedule
jobRepository.save(job);
...
}
when I checked the log, i found this :
Hibernate:
delete
from
`schedules_to_groups`
where
schedule_id=?
Hibernate:
insert
into
`
jobs_to_groups` (
job_id, group_id
)
values
(?, ?)
so hibernate deleted the relationship between schedule and groups right before it insert job and its groups, but why?