Spring Data JPA + Spring Batch + Hibernate和Bidirectional @OneToMany关系

时间:2016-07-10 17:56:31

标签: hibernate jpa spring-batch spring-data-jpa

我发现标准做法的行为不一致,并且通过Spring Data JPA作为Spring Batch作业的一部分来保持JPA双向关系。我的工作步骤如下:

@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();
}

这两个域是Patient(父)和Encounter(子)。它们如下所示:

@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
}

接下来,假设所有患者都已从源数据库中读入并作为上一步骤的一部分保留。执行的下一步是通过带有JdbcPagingItemReader<Encounter>的{​​{1}}读取所有遭遇者(孩子)。 RowMapper<Encounter>代码如下所示:

RowMapper

然后将@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; } } 传递给Encounter,将遇到者保存到RepositoryItemWriter<Encounter>

我的理解是,这不是最佳做法,原因如下:

  1. 我应该做EncounterRepository;但是,我认为这不适合RowMapper应该做的事情。也许我错在这里。可以将其移至patient.getEncounters.add(encounter)并将ItemProcessor<Encounter, Patient>更改为ItemWriter。不过,我会不断地坚持我的父母,如果这个孩子是这个关系的所有者,这是不理想的 - 父母也不会改变。
  2. 我很可能通过不做#1看到Hibernate缓存问题。似乎并非如此。我已通过我的Spring MVC控制确认,在作业完成后,我的所有域(包括上面的那个)中的父和子关系看起来都符合预期,并且在我的代码中没有ItemWriter<Patient>
  3. 我在整个应用程序中有很多双向关系。我读过双向关系很糟糕,应该用存储库替换,但我没有看到使用Spring Batch的patient.getEncounters.add(encounter)ItemReaderItemProcessor模型做到这一点的好方法。
  4. 希望有人能帮助我理解为什么我没有看到#2和#1&amp; #3。

0 个答案:

没有答案