use*_*382 1 java eclipse hibernate jpa
出于某种原因,我无法删除属于多对多关系的对象.我收到以下错误:
Exception in thread "main" org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [edu.cs157b.hibernate.AppointmentRequest#11]
at org.hibernate.internal.SessionImpl.forceFlush(SessionImpl.java:1232)
Run Code Online (Sandbox Code Playgroud)
这是我的三个类,它们映射了多对多的关系.从本质上讲,Doctor有很多Patients通过AppointmentRequest,反之亦然.这是课程
医生
package edu.cs157b.hibernate;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
@Entity
@Table(name="DOCTOR_INFO")
@NamedQueries (
{
@NamedQuery(name = "Doctor.getAll", query = "from Doctor"),
@NamedQuery(name = "Doctor.findByName", query = "from Doctor where name = :name")
}
)
public class Doctor implements Person {
private int id;
private String name;
private Specialty specialty;
private List<AppointmentRequest> appointmentRequests = new ArrayList<AppointmentRequest>();
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(unique=true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne (fetch = FetchType.EAGER, cascade= CascadeType.PERSIST)
@JoinColumn(name="specialty_id")
public Specialty getSpecialty() {
return specialty;
}
public void setSpecialty(Specialty specialty) {
this.specialty = specialty;
}
@OneToMany(mappedBy="doctor", targetEntity = AppointmentRequest.class,
fetch=FetchType.EAGER, orphanRemoval=true, cascade= CascadeType.ALL)
public List<AppointmentRequest> getAppointmentRequests() {
return this.appointmentRequests;
}
public void setAppointmentRequests(List<AppointmentRequest> appointmentRequests) {
this.appointmentRequests = appointmentRequests;
}
@Transient
public List<Patient> getPatients() {
List<Patient> patients = new ArrayList<Patient>();
for(AppointmentRequest appointment:appointmentRequests) {
patients.add(appointment.getPatient());
}
return patients;
}
}
Run Code Online (Sandbox Code Playgroud)
患者
package edu.cs157b.hibernate;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
@Entity
@Table(name="PATIENT_INFO")
@NamedQueries (
{
@NamedQuery(name = "Patient.getAll", query = "from Patient"),
@NamedQuery(name = "Patient.findByName", query = "from Patient where name = :name")
}
)
public class Patient implements Person {
private int id;
private String name;
private String medical_record;
private List<AppointmentRequest> appointmentRequests = new ArrayList<AppointmentRequest>();
public String getMedical_record() {
return medical_record;
}
public void setMedical_record(String medical_record) {
this.medical_record = medical_record;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Column(unique=true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@OneToMany(mappedBy="patient", targetEntity = AppointmentRequest.class,
fetch=FetchType.EAGER, orphanRemoval=true, cascade= CascadeType.ALL)
public List<AppointmentRequest> getAppointmentRequests() {
return this.appointmentRequests;
}
public void setAppointmentRequests(List<AppointmentRequest> appointmentRequests) {
this.appointmentRequests = appointmentRequests;
}
@Transient
public List<Doctor> getDoctors() {
List<Doctor> doctors = new ArrayList<Doctor>();
for(AppointmentRequest appointment:appointmentRequests) {
doctors.add(appointment.getDoctor());
}
return doctors;
}
}
Run Code Online (Sandbox Code Playgroud)
ApppointmentRequest
package edu.cs157b.hibernate;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.TimeZone;
import javax.persistence.*;
import org.hibernate.annotations.Type;
import java.util.List;
@Entity
@Table(name="APPOINTMENT_REQUEST")
@NamedQueries (
{
@NamedQuery(name = "AppointmentRequest.getAll", query = "from AppointmentRequest"),
@NamedQuery(name = "AppointmentRequest.findByDoctorId", query = "from AppointmentRequest where doctor_id = :doctor_id"),
@NamedQuery(name = "AppointmentRequest.findByPatientId", query = "from AppointmentRequest where patient_id = :patient_id"),
@NamedQuery(name = "AppointmentRequest.findByID", query = "from AppointmentRequest where id = :id")
}
)
public class AppointmentRequest {
private int id;
private Doctor doctor;
private Patient patient;
private boolean fulfilled = false;
private Calendar time;
private final SimpleDateFormat timestampFormat = new SimpleDateFormat("MM/dd/yyyy h a");
public Calendar getTime() {
return time;
}
@Transient
public String getFormattedTime() {
String result = timestampFormat.format(time.getTime());
return result;
}
public void setTime(Calendar time) {
this.time = time;
}
public boolean isFulfilled() {
return fulfilled;
}
public void setFulfilled(boolean fulfilled) {
this.fulfilled = fulfilled;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@ManyToOne (fetch = FetchType.EAGER, cascade= CascadeType.PERSIST)
@JoinColumn(name="doctor_id")
public Doctor getDoctor() {
return doctor;
}
public void setDoctor(Doctor doctor) {
this.doctor = doctor;
}
@ManyToOne (fetch = FetchType.EAGER, cascade= CascadeType.PERSIST)
@JoinColumn(name="patient_id")
public Patient getPatient() {
return patient;
}
public void setPatient(Patient patient) {
this.patient = patient;
}
}
Run Code Online (Sandbox Code Playgroud)
医生删除方法
public void deleteDoctor(String doctor_name) {
Session session = sessionFactory.openSession();
Doctor doctor = new Doctor();
try {
session.beginTransaction();
Query query = session.getNamedQuery("Doctor.findByName");
query.setString("name", doctor_name);
doctor = (Doctor) query.uniqueResult();
if(doctor == null) {
throw new NullPointerException();
}
List<AppointmentRequest> appointments = doctor.getAppointmentRequests();
for(AppointmentRequest appointment:appointments) {
appointment.setDoctor(null);
}
session.delete(doctor);
session.getTransaction().commit();
}
finally {
session.close();
}
}
Run Code Online (Sandbox Code Playgroud)
这个异常的真正含义是你告诉Hibernate从数据库中删除对象,但同时这个对象仍然存在(这意味着仍然存在于java或数据库中)在映射集合中通过Persistent实体CascadeType.PERSIST注释了它.
这就像在窗户上用弹性橡胶捆绑的东西,然后捅它,希望它会下降.Hibernate很聪明,它可以帮助你避免做无意义的事情,它会告诉你该怎么做
已删除的对象将通过级联重新保存(从关联中删除已删除的对象)
正弦你正在做appointment.setDoctor(null);它会删除对象从集合(仅在Java中,你是不明确或隐含更新appointment).你必须CascadeType.PERSIST在doctor这意味着当Hibernate会提交它会发现交易是appointment有关联doctor刚刚删除,这意味着如果你doctor从表中删除它,hibernate必须去创建相同的,doctor因为你没有告诉他进行适当的更改,appointment因为他遵循你设置的所有实体规则.由于hibernate是聪明的,他知道这一点,他会抛出一个例外,说你不要做矛盾,做正确的事.
现在我可以在这里考虑多个解决方案
使用cascade={CascadeType.PERSIST,CascadeType.REMOVE}或 cascade=CascadeType.ALL对getDoctor()中AppointmentRequest
由于休眠文件中提到这里
在@ManyToOne或@ManyToMany关联上启用级联通常没有意义.Cascade通常对@OneToOne和@OneToMany关联有用.
从中删除级联 getDoctor
既然你FetchType.EAGER在getDoctor()使用cascade指定为我解释休眠的行为,但它是有点复杂,这个问题他们已经通过解决FetchType.LAZY我不知道这是否会制定出适合您.
你可以做session.saveOrUpdate(appointment)所有AppointmentRequest有这位医生然后去的人session.delete(doctor);
希望你能解决你的问题.
| 归档时间: |
|
| 查看次数: |
6758 次 |
| 最近记录: |