Hibernate中的有效更新实体
我想这可能像一个新手问题,但我仍然想知道一些答案。
假设有实体:医院和医生( )。假设在我的控制者班级中,我必须先找所有现有的医生和医院,然后再在特定的医院雇用一名医生
@Controllerpublic class HospitalController {
...
@RequestMapping("/hireDoctor")
public String (HttpServletRequest request, Model model) {
List<Hospital> hospitals = hospitalService.findAllHospitals();
List<Doctor> doctors = doctorService.findAllDoctors();
//some logic, in the end we choose just one doctor and one hospital
Doctor doctor = doctors.get(0);
Hospital hospital = hospitals.get(0);
hospitalService.hireDoctor(hospital, doctor);
}
...
@Service
public class HospitalService {
..
@Transactional
public void hireDoctor(Hospital hospital, Doctor doctor) {
//ideally
List<Doctor> doctors = hospital.getDoctors();
doctors.add(doctor);
this.em.merge(hospital);
}
..
}
它当然不起作用,因为-据我了解-
我已经在控制器中获取了所有医生和医院,然后在hireDoctor方法中,我们通过常规Java对象(不在会话中)打开了事务处理。
我知道,我可以再次获取带有特定ID的医院,以及具有特定ID的Doctor,然后将其保存
public void hireDoctor(Hospital hospital, Doctor doctor) { Hospital h = hospitalRepo.getHospitalById(hospital.getId());
Doctor d = hospitalRepo.getDoctorById(doctor.getId());
List<Doctor> doctors = h.getDoctors();
doctors.add(d);
}
但这看起来只是垃圾。
那么-这样的更新看起来如何最有效?
回答:
有一个很好的方法可以做到这一点。它依赖于结合使用Hibernate代理和提取与一个单独实体的多对多关系,例如:
@Entitypublic class HospitalToDoctor implements Serializable {
@Id
@ManyToOne
private Hospital hospital;
@Id
@ManyToOne
private Doctor doctor;
}
@Entity
public class Hospital {
@OneToMany(mappedBy = "hospital")
private Collection<HospitalToDoctor> doctors;
}
@Entity
public class Doctor {
@OneToMany(mappedBy = "doctor")
private Collection<HospitalToDoctor> hospitals;
}
现在,仅使用一个insert语句来关联a Doctor
和a Hospital
,而无需进行任何其他数据库往返操作:
HospitalToDoctor hospitalToDoctor = new HospitalToDoctor();hospitalToDoctor.setHospital(entityManager.getReference(Hospital.class, hospitalId));
hospitalToDoctor.setDoctor(entityManager.getReference(Doctor.class, doctorId));
entityManager.persist(hospitalToDoctor);
这里的关键点是使用EntityManager.getReference:
获取一个实例,其状态可能会延迟获取。
Hibernate只会根据提供的ID创建代理,而无需从数据库中获取实体。
在其他用例中,您可以封装HospitalToDoctor
实体,以便仍然使用多对多关联。例如,您可以添加Hopsital
如下内容:
public Collection<Doctor> getDoctors() { Collection<Doctor> result = new ArrayList<>(doctors.size());
for (HospitalToDoctor hospitalToDoctor : doctors) {
result.add(hospitalToDoctor.getDoctor());
}
return result;
}
引入的另一个好处HospitalToDoctor
是,如果需要,您可以轻松地在其中存储其他属性(例如,当医生开始在医院工作时等)。
但是,如果您仍然不想引入单独的实体,而是想要使用干净的多对多Hibernate,仍然可以从代理中受益。您可以将Doctor
代理添加到已加载的代理中Hospital
(反之亦然)。您可能还希望查看Hibernate额外的惰性集合,以避免doctors
在将a添加Doctor
到a时Hospital
反之亦然(反之亦然)(我想这是您问题的主要关注点),以避免加载该集合。
以上是 Hibernate中的有效更新实体 的全部内容, 来源链接: utcz.com/qa/398238.html