So I have a schedule object which contains a list of DateActiveScheduleItem.I am obtaining the schedule from the database,removing a DateActiveScheuleItem from the list,and saving it using .save() from Hibernate CrudRepository.
nested exception is org.springframework.orm.jpa.JpaSystemException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: haughton.daniel.ShoutLoud.model.schedule.Schedule.dateActiveScheduleItems; nested exception is org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: haughton.daniel.ShoutLoud.model.schedule.Schedule.dateActiveScheduleItems] with root causeorg.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: haughton.daniel.ShoutLoud.model.schedule.Schedule.dateActiveScheduleItems
Schedule.java
@Entity
public class Schedule {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id")
private User user;
@ManyToOne
@JoinColumn(name = "usergroup_id")
private UserGroup userGroup;
private String description;
private boolean master;//is this a schedule for all supervalus(true) or one supervalu(false)
@OneToMany(mappedBy = "schedule",cascade = CascadeType.ALL,orphanRemoval=true)
private List<DateActiveScheduleItem> dateActiveScheduleItems = new ArrayList<>();
@OneToMany(mappedBy = "schedule",cascade = CascadeType.PERSIST)
private List<MusicScheduleItem> musicScheduleItems = new ArrayList<>();
@OneToMany(mappedBy = "schedule",cascade = CascadeType.PERSIST)
private List<AdvertisementScheduleItem> advertisementScheduleItems = new ArrayList<>();
@Basic
@Temporal(TemporalType.DATE)
private java.util.Date dateAdded;
public Long getId() {
return id;
}
public Date getDateAdded() {
return dateAdded;
}
public void setDateAdded(Date dateAdded) {
this.dateAdded = dateAdded;
}
public void setId(Long id) {
this.id = id;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public UserGroup getUserGroup() {
return userGroup;
}
public void setUserGroup(UserGroup userGroup) {
this.userGroup = userGroup;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isMaster() {
return master;
}
public void setMaster(boolean master) {
this.master = master;
}
public List<DateActiveScheduleItem> getDateActiveScheduleItems() {
return dateActiveScheduleItems;
}
public void setDateActiveScheduleItems(List<DateActiveScheduleItem> dateActiveScheduleItems) {
this.dateActiveScheduleItems = dateActiveScheduleItems;
}
public List<AdvertisementScheduleItem> getAdvertisementScheduleItems() {
return advertisementScheduleItems;
}
public void setAdvertisementScheduleItems(List<AdvertisementScheduleItem> advertisementScheduleItems) {
this.advertisementScheduleItems = advertisementScheduleItems;
}
public List<MusicScheduleItem> getMusicScheduleItems() {
return musicScheduleItems;
}
public void setMusicScheduleItems(List<MusicScheduleItem> musicScheduleItems) {
this.musicScheduleItems = musicScheduleItems;
}
public boolean removeDateActiveScheduleItem(Date date){
for(int i =0;i<dateActiveScheduleItems.size();i++){
if(date.getTime()==dateActiveScheduleItems.get(i).getDate().getTime()){
dateActiveScheduleItems.remove(i);
return true;
}
}
return false;
}
public boolean isScheduleActiveToday(){
Calendar now = Calendar.getInstance();
for(int i=0;i<dateActiveScheduleItems.size();i++){
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal1.setTime(now.getTime());
cal2.setTime(dateActiveScheduleItems.get(i).getDate());
boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
if(sameDay==true){
return true;
}
}
return false;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Schedule schedule = (Schedule) o;
if (master != schedule.master) return false;
if (id != null ? !id.equals(schedule.id) : schedule.id != null) return false;
if (user != null ? !user.equals(schedule.user) : schedule.user != null) return false;
if (userGroup != null ? !userGroup.equals(schedule.userGroup) : schedule.userGroup != null) return false;
if (description != null ? !description.equals(schedule.description) : schedule.description != null)
return false;
if (dateActiveScheduleItems != null ? !dateActiveScheduleItems.equals(schedule.dateActiveScheduleItems) : schedule.dateActiveScheduleItems != null)
return false;
if (musicScheduleItems != null ? !musicScheduleItems.equals(schedule.musicScheduleItems) : schedule.musicScheduleItems != null)
return false;
if (advertisementScheduleItems != null ? !advertisementScheduleItems.equals(schedule.advertisementScheduleItems) : schedule.advertisementScheduleItems != null)
return false;
return dateAdded != null ? dateAdded.equals(schedule.dateAdded) : schedule.dateAdded == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (user != null ? user.hashCode() : 0);
result = 31 * result + (userGroup != null ? userGroup.hashCode() : 0);
result = 31 * result + (description != null ? description.hashCode() : 0);
result = 31 * result + (master ? 1 : 0);
result = 31 * result + (dateActiveScheduleItems != null ? dateActiveScheduleItems.hashCode() : 0);
result = 31 * result + (musicScheduleItems != null ? musicScheduleItems.hashCode() : 0);
result = 31 * result + (advertisementScheduleItems != null ? advertisementScheduleItems.hashCode() : 0);
result = 31 * result + (dateAdded != null ? dateAdded.hashCode() : 0);
return result;
}
}
DateActiveScheduleItem
@Entity
public class DateActiveScheduleItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Basic
@Temporal(TemporalType.DATE)
private Date date;
public Schedule getSchedule() {
return schedule;
}
public void setSchedule(Schedule schedule) {
this.schedule = schedule;
}
@JsonIgnore
@ManyToOne
@JoinColumn(name = "schedule_id")
private Schedule schedule;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DateActiveScheduleItem that = (DateActiveScheduleItem) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if (date != null ? !date.equals(that.date) : that.date != null) return false;
return schedule != null ? schedule.equals(that.schedule) : that.schedule == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (date != null ? date.hashCode() : 0);
result = 31 * result + (schedule != null ? schedule.hashCode() : 0);
return result;
}
}
In my controller
This error occurs when saving any Schedule where the DateActiveScheduleItem list has anything in it
all-delete-orphan - when an object is save/update/delete, check the associations and save/update/delete all the objects found. In additional to that, when an object is removed from the association and not associated with another object (orphaned), also delete it.
If orphanRemoval=true is specified the disconnected Address instance is automatically removed. This is useful for cleaning up dependent objects (e.g. Address ) that should not exist without a reference from an owner object (e.g. Employee ).
When a target entity in one-to-one or one-to-many relationship is removed from the relationship, it is often desirable to cascade the remove operation to the target entity. Such target entities are considered “orphans,” and the orphanRemoval attribute can be used to specify that orphaned entities should be removed.
The meaning of CascadeType. ALL is that the persistence will propagate (cascade) all EntityManager operations ( PERSIST, REMOVE, REFRESH, MERGE, DETACH ) to the relating entities. It seems in your case to be a bad idea, as removing an Address would lead to removing the related User .
Most common problem is to overwrite your collection rather than add to it.
If you happend to do something like that :
post.dateActiveScheduleItems = list;
This may cause following problem. Rather than that try this.
post.dateActiveScheduleItems.addAll(list);
You should work with one instance of your collection, just clear it, add to it, never overwrite.
Rempove orphanRemoval=true from here.
@OneToMany(mappedBy = "schedule",cascade = CascadeType.ALL,orphanRemoval=true)
This might also happen in (spring boot application) testing context, with the maven-surefire-plugin reuseForks set on true. The cause, in that context, are database records that are leaked between tests.
To fix the issue it is necessary to either properly clean up the test environment after running a test class, or cleanup the database test environment before running a test class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With