Невозможно удалить объект из коллекции ManyToMany после его сохранения
Моя следующая проблема заключается в том, что я не могу удалить сущность с обратной стороны manyToMany после сохранения собственной стороны. Это применимо только если это делается через ajax. Я могу удалить его, если обновлю страницу.
Владелец объекта с методами защитной ссылки:
@Entity
@Table(name = "..._drive")
public class Drive extends Identity {
private List<UAnalysis> uAnalyses = new ArrayList<>();
public Drive() {
}
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST})
@JoinTable(
name = "..._drive_uanalysis",
joinColumns = @JoinColumn(name = "drive_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "uanalysis_id", referencedColumnName = "id")
)
public List<UAnalysis> getUAnalyses() {
return uAnalyses;
}
public void setUAnalyses(List<UAnalysis> uAnalyses) {
this.uAnalyses = uAnalyses;
}
public void addUAnalysis(UAnalysis uAnalysis) {
this.getUAnalyses().add(uAnalysis);
uAnalysis.getDrives().add(this);
}
public void removeUAnalysis(UAnalysis uAnalysis) {
this.getUAnalyses().remove(uAnalysis);
uAnalysis.getDrives().remove(this);
}
}
Инверсная сущность:
@Entity
@Table(name = "..._uanalysis")
public class UAnalysis extends Analysis {
//Fields
List<Drive> drives = new ArrayList<>();
public UAnalysis() {
}
@ManyToMany(mappedBy = "uAnalyses")
public List<Drive> getDrives() {
return drives;
}
public void setDrives(List<Drive> drives) {
this.drives = drives;
}
//Other Getter and Setter
}
В моем driveBean я добавляю UAnalysis на диск перед сохранением:
@Named
@ViewScoped
public class DriveBean extends GenericBean<Drive, DriveService> {
public void attachUAnalysis(UAnalysis uAnalysis) {
if(analysisService.isDetached(uAnalysis)) {
uAnalysis = (UAnalysis) analysisService.merge(uAnalysis);
}
getSelectedEntity().addUAnalysis(uAnalysis);
getService().save(getSelectedEntity());
}
private void detachUAnalysis(UAnalysis uAnalysis) {
if(analysisService.isDetached(uAnalysis)) {
uAnalysis = (UAnalysis) analysisService.merge(uAnalysis);
}
getSelectedEntity().removeUAnalysis(uAnalysis);
getService().save(getSelectedEntity());
}
}
Как я читал в этой теме Дилемма JPA hashCode() / equals(), это может быть проблемой, связанной с методом equals () или hashCode (). Я попытался изменить возвращаемое значение hashCode () на фиксированное значение, но это не помогло. В настоящее время это реализовано следующим образом:
@MappedSuperclass
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public abstract class Identity implements IIdentity {
@Override
public int hashCode() {
return (int) (getId() ^ (getId() >>> 32));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof IIdentity)) return false;
IIdentity identity = (IIdentity) o;
return getId() != null && Objects.equals(getId(), identity.getId());
}
private Long id;
//GenerationType.TABLE is needed because of TABLE_PER_CLASS inheritance
//MySQL does not have sequences thus a sequence cannot be used
@Id
@GeneratedValue(generator = "..._table_generator", strategy = GenerationType.TABLE)
@TableGenerator(name = "..._table_generator", initialValue = 1000)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
Я также обнаружил, что это может быть проблема с кэшем L2, но очистка после сохранения диска также не решает проблему.
UUID не может быть использован, так как производительность имеет большое значение.
Я в настоящее время не имею понятия, что вызывает проблему.
РЕДАКТИРОВАТЬ 1: Что я испытываю, так это то, что после вставки нового объекта коллекции uAnalysis, hibernate удаляет все строки с идентификатором диска, а затем вставляет каждую отдельную строку снова. Это то, что указало мне на проблему равенства и hashCode
Hibernate: delete from ..._drive_uanalysis where drive_id=?
Hibernate: insert into ..._drive_uanalysis (drive_id, uanalysis_id) values (?, ?)
Hibernate: insert into ..._drive_uanalysis (drive_id, uanalysis_id) values (?, ?)