Hibernate Spring数据JPA+;弹簧批+;休眠和双向@OneToMany关系
我看到了与标准实践不一致的行为,并将通过SpringDataJPA保持JPA双向关系作为SpringBatch作业的一部分。我的工作步骤如下所示:Hibernate Spring数据JPA+;弹簧批+;休眠和双向@OneToMany关系,hibernate,jpa,spring-batch,spring-data-jpa,Hibernate,Jpa,Spring Batch,Spring Data Jpa,我看到了与标准实践不一致的行为,并将通过SpringDataJPA保持JPA双向关系作为SpringBatch作业的一部分。我的工作步骤如下所示: @Bean public Step importSinglePatient(StepBuilderFactory stepBuilderFactory, ItemReader<Patient> singlePatientReader,
@Bean
public Step importSinglePatient(StepBuilderFactory stepBuilderFactory,
ItemReader<Patient> singlePatientReader,
ItemWriter<Patient> patientWriter) {
return stepBuilderFactory.get("importSinglePatient")
.<Patient, Patient>chunk(1)
.reader(singlePatientReader)
.writer(patientWriter)
.build();
}
@Bean
public Step importSingleEncounter(StepBuilderFactory stepBuilderFactory,
ItemReader<Encounter> singleEncounterReader,
ItemWriter<Encounter> encounterWriter) {
return stepBuilderFactory.get("importSingleEncounter")
.<Encounter, Encounter>chunk(1)
.reader(singleEncounterReader)
.writer(encounterWriter)
.build();
}
@Entity
public class Patient implements Serializable {
public static final long serialVersionUID = 1L;
@Id
private Long patientId;
@OneToMany(mappedBy = "patient", cascade = CascadeType.ALL)
private List<Encounter> encounters;
// getters & setters
}
@Entity
public class Encounter implements Serializable {
public static final long serialVersionUID = 1L;
@Id
private Long encounterId;
@ManyToOne
@JoinColumn(name = "patient_id")
private Patient patient;
// getters & setters
}
@Component
public class EncounterRowMapper implements RowMapper<Encounter> {
@Autowired
private PatientRepository patientRepository
public static final String PATIENT_ID = "PATIENT_ID";
@Override
public Encounter mapRow(ResultSet rs, int rowNum) throws SQLException {
Encounter encounter = new Encounter;
Patient patient = patientRepository.findOne(rs.getLong(PATIENT_ID));
encounter.setPatient(patient);
return encounter;
}
}
接下来,假设所有患者都已从源数据库读入,并作为前一步的一部分进行了持久化。执行的下一步是使用行映射器通过JdbcPagingItemReader
读取所有遭遇(子项)。RowMapper
代码如下所示:
@Bean
public Step importSinglePatient(StepBuilderFactory stepBuilderFactory,
ItemReader<Patient> singlePatientReader,
ItemWriter<Patient> patientWriter) {
return stepBuilderFactory.get("importSinglePatient")
.<Patient, Patient>chunk(1)
.reader(singlePatientReader)
.writer(patientWriter)
.build();
}
@Bean
public Step importSingleEncounter(StepBuilderFactory stepBuilderFactory,
ItemReader<Encounter> singleEncounterReader,
ItemWriter<Encounter> encounterWriter) {
return stepBuilderFactory.get("importSingleEncounter")
.<Encounter, Encounter>chunk(1)
.reader(singleEncounterReader)
.writer(encounterWriter)
.build();
}
@Entity
public class Patient implements Serializable {
public static final long serialVersionUID = 1L;
@Id
private Long patientId;
@OneToMany(mappedBy = "patient", cascade = CascadeType.ALL)
private List<Encounter> encounters;
// getters & setters
}
@Entity
public class Encounter implements Serializable {
public static final long serialVersionUID = 1L;
@Id
private Long encounterId;
@ManyToOne
@JoinColumn(name = "patient_id")
private Patient patient;
// getters & setters
}
@Component
public class EncounterRowMapper implements RowMapper<Encounter> {
@Autowired
private PatientRepository patientRepository
public static final String PATIENT_ID = "PATIENT_ID";
@Override
public Encounter mapRow(ResultSet rs, int rowNum) throws SQLException {
Encounter encounter = new Encounter;
Patient patient = patientRepository.findOne(rs.getLong(PATIENT_ID));
encounter.setPatient(patient);
return encounter;
}
}
@组件
公共类遇到错误Apper实现行映射器{
@自动连线
私人病人
公共静态最终字符串PATIENT\u ID=“PATIENT\u ID”;
@凌驾
公共遭遇映射行(ResultSet rs,int rowNum)抛出SQLException{
遭遇=新的遭遇;
患者=患者阳性。芬顿(rs.getLong(患者ID));
遭遇。设定病人(病人);
回击;
}
}
然后将遭遇
传递给RepositoryItemWriter
,后者将遭遇保存到遭遇库
我的理解是,这不是最佳做法,原因如下:
我应该做一个病人.getConferences.add(遭遇)
;然而,我认为这并不适合划船制图员应该做的事情。也许我错了。可以将其移动到ItemProcessor
并将ItemWriter
改为ItemWriter
。不过,我会一直坚持我的父母,如果孩子是这段关系的主人,这并不理想——父母也不会改变
如果不执行#1,我很可能会看到Hibernate缓存问题。事实似乎并非如此。我已经通过Spring MVC Controld确认,在工作完成后,在我的所有域(包括上面的域)中,父域和子域的关系看起来都与预期的一样,并且没有在我的代码中的任何地方执行patient.getConferences.add(Conference)
在整个应用程序中,我有很多双向关系。我读到过双向关系不好,应该用存储库来代替,但我认为Spring Batch的ItemReader
、ItemProcessor
和ItemWriter
模型没有好的方法来实现这一点
希望有人能帮助我理解为什么我看不到第2个和对第1个和第3个的想法。您意识到从ItemReader
返回的项目在您使用RepositoryItemWriter
持久化之前与hibernate没有关联,对吗?这只是一个普通的POJO,是的,我理解。我试图理解不执行patient.getConferences.add(Conference)在我的代码中的任意位置为双向关系的另一端添加(Conference)的后果。将遭遇添加到列表在我的代码中不存在,但在遭遇被持久化后,我仍然可以通过控制器看到我的关系的预期行为。双向关系是OO代码中的一个概念…而不是关系数据库。当您检索新对象时,您的JPA提供程序(假设为Hibernate)会为您处理额外的内容。看起来我想得太多了。您意识到从ItemReader
返回的项目与hibernate不关联,直到您使用RepositoryItemWriter
将其持久化,对吗?这只是一个普通的POJO,是的,我理解。我试图理解不执行patient.getConferences.add(Conference)在我的代码中的任意位置为双向关系的另一端添加(Conference)的后果。将遭遇添加到列表在我的代码中不存在,但在遭遇被持久化后,我仍然可以通过控制器看到我的关系的预期行为。双向关系是OO代码中的一个概念…而不是关系数据库。当您检索新对象时,您的JPA提供程序(假设为Hibernate)会为您处理额外的内容。看来我想得太多了。