我有一个非常标准的Spring Data JPA / Hibernate @OnetoMany关系,它按预期保持不变,但是当我选择父级时,没有检索到子级。
这是我的父母:
@Entity
@Table(name = "APPOINTMENT")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "appointmentId")
public class Appointment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long appointmentId;
@OneToMany(mappedBy = "appointment", fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<AppointmentProcedureItems> appointmentProcedureItems = new ArrayList<>();
...
}
然后是孩子:
@Entity
@Table(name = "APPOINTMENTPROCEDUREITEMS")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class,
property = "appointmentProcedureItemId")
public class AppointmentProcedureItems {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long appointmentProcedureItemId;
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "appointmentId", nullable = false)
private Appointment appointment;
...
}
当我从UI收到约会和嵌套的appointmentProcedureItems作为DTO时,我这样做:
appointment.setAppointmentProcedureItems(appointmentProcedureItemsDTOConvertor.convertDTOListForOffice(dto.getAppointmentProcedureItemsDTO(), null, appointment));
...
public List<AppointmentProcedureItems> convertDTOListForOffice(List<AppointmentProcedureItemsDTO> dtoList,
Office office, Appointment appointment) {
List<AppointmentProcedureItems> appointmentProcedureItemsList = new ArrayList<>();
for (AppointmentProcedureItemsDTO dto : dtoList) {
AppointmentProcedureItems item = convertAppointmentProcedureItemsDTO(dto, office);
item.setAppointment(appointment);
appointmentProcedureItemsList.add(item);
}
return appointmentProcedureItemsList;
}
我只想检索:
@Repository
public interface AppointmentRepository extends CrudRepository<Appointment, Long>, JpaSpecificationExecutor<Appointment>,
QueryDslPredicateExecutor<Appointment> {
List<Appointment> findByOfficeIdAndStartDateTimeBetween(@Param("officeId") Long officeId,
@Param("startDateTime") ZonedDateTime startDateTime,
@Param("endDateTime") ZonedDateTime endDateTime);
..
}
和被叫服务:
List<Appointment> foundAppointments = appointmentRepository
.findByOfficeIdAndStartDateTimeBetween(office.getOfficeId(), startAppointmentDate,
endAppointmentDate);
这是我的一个测试:
def "create appointments, then try to change one operatory to be a conflict"() {
def office = officeService.findByURL("myoffice")
def startTime = LocalDateTime.of(2015, 11, 27, 11, 30)
def maryApt = new Appointment(officeId: office.getOfficeId(), providerId: 10l, patientId: 1L,
patientFirstName: "Mary", patientLastName: "Lamb" , title: Title.MISS,
description: "test appointment #1 ", procedureId: 11l,
startDateTime: DateUtil.convertToUTCZoneDateTime(startTime), endDateTime: DateUtil.convertToUTCZoneDateTime(startTime.plusMinutes(30)),
operatory: new Operatory(id:1l, name: "operatory 1", officeId: office.getOfficeId(),employeeId:1l), employee: new Employee(fullName: "test Employee", office: office),
appointmentDefinition: new AppointmentDefinition(appointmentDefinitionId: new Long(1L), officeId: office.getOfficeId(),
description: "test description", duration: 10, colorCode: "red",
providertype: AppointmentProvider.DENTIST))
maryApt.getAppointmentProcedureItems().add(new AppointmentProcedureItems(appointmentProcedureItemId: 1L,
providerId: 1L, procedureId: 1L, code: "One", description: "descript one", note: "note 1",
price: new BigDecimal("1.0"), patientId: 1L))
def maryAppointment = appointmentService.saveAppointment(maryApt)
def davidApt = new Appointment(officeId: office.getOfficeId(), providerId: 10l, patientId: 2L,
patientFirstName: "David", patientLastName: "Lamb" , title: Title.MISS,
description: "test appointment #1 ", procedureId: 11l,
startDateTime: DateUtil.convertToUTCZoneDateTime(startTime), endDateTime: DateUtil.convertToUTCZoneDateTime(startTime.plusMinutes(30)),
operatory: new Operatory(id:2l, name: "operatory 2", officeId: office.getOfficeId(),employeeId:1l), employee: new Employee(fullName: "test Employee", office: office),
appointmentDefinition: new AppointmentDefinition(appointmentDefinitionId: new Long(1L), officeId: office.getOfficeId(),
description: "test description", duration: 10, colorCode: "red",
providertype: AppointmentProvider.DENTIST))
appointmentService.saveAppointment(davidApt)
maryAppointment.setOperatory(new Operatory(id:2l, name: "operatory 2", officeId: office.getOfficeId(),employeeId:1l))
def maryDto = appointmentDTOConverter.convert(maryAppointment, office)
expect:
true == appointmentService.hasDuplicate(maryDto)
maryDto.getAppointmentProcedureItemsDTO().size() == 1
maryDto.getAppointmentProcedureItemsDTO().findAll {
it.procedureId == 1L && it.code == "One" && it.note == "note 1" && it.description == "descript one" && it.officeId == office.getOfficeId() && it.patientId == 1L
}.size() == 1
}
我的表上没有任何参照完整性,我可以检查两个表并查看是否填充了约会并填充了相应的appointmentprocedureitems表,其中的appointmentId列中包含正确的约会ID。
我感到惊讶的是,坚持有效而不是检索 - 不知道我以前见过这种特殊的行为。我在这个项目中有很多相同的@OneToMany双向关系,在我看来它们都有相同的映射。