I have having issues trying to do a batch insert operation using Spring Data JPA with Hibernate as the JPA provider.
I have the following method in my service. This is where the exception is being thrown.
@Transactional
private void saveAppointments() {
// create StageFile reference object
StageFile file = new StageFile();
file.setFileName("3312_APPOINTMENT.API");
file.setDeleteFlag('N');
file.setInstitution(institution);
for (StageAppointment appointment : appointments) {
appointment.setStageFile(file);
stageAppointmentRepository.save(appointment);
}
}
@Transactional
private void saveDepartments() {
// create StageFile reference object
StageFile file = new StageFile();
file.setFileName("3312_DEPARTMENT.API");
file.setDeleteFlag('N');
file.setInstitution(institution);
for (StageDepartment department : departments) {
department.setStageFile(file);
stageDepartmentRepository.save(department);
}
}
The institution is an instance variable and fetched ahead of time.
Institution institution = institutionRepository.findByActCode(3312);
I also have the Entity set to cascade PERSIST and MERGE.
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "stgAppointmentSeq")
@SequenceGenerator(name = "stgAppointmentSeq", sequenceName = "T_STG_APPOINTMENT_SEQ", allocationSize = 50)
@Column(name = "ID")
private Long id;
@ManyToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE}, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "FILE_ID", referencedColumnName = "ID")
private StageFile stageFile;
@ManyToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE}, fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "STATUS_ID", referencedColumnName = "ID")
private StageStatus stageStatus;
What am I doing wrong?
Also I'm sure the answer to this question is Yes, but when I persist an Entity that has a required foreign key reference do I have to save the full associated object or just the ID? Seems counter to the purpose of JPA though.
Update:
Per comments I updated the code to perform everything within the single transaction but it made no difference.
@Transactional
private void saveAppointments() {
Institution institution = institutionRepository.findByActCode(3312);
StageStatus stageStatus = stageStatusRepository.findOne(1L);
// create StageFile reference object
StageFile file = new StageFile();
file.setFileName("3312_APPOINTMENT.API");
file.setDeleteFlag('N');
file.setInstitution(institution);
for (StageAppointment appointment : appointments) {
appointment.setStageFile(file);
appointment.setStageStatus(stageStatus);
stageAppointmentRepository.save(appointment);
}
}
UPDATE 2:
Why does this code work
@Transactional
private void saveUsingTransaction() {
Institution institution = institutionRepository.findByActCode(3312);
StageStatus status = stageStatusRepository.findOne(1L);
StageFile file = new StageFile();
file.setDeleteFlag('N');
file.setFileName("3312_DIRECTORY.API");
file.setInstitution(institution);
StageDirectory directory = new StageDirectory();
directory.setLocalId("11111111111111111");
directory.setFirstName("Joe");
directory.setLastName("Joe");
directory.setPrimaryEmail("joe@gmail.com");
directory.setStageFile(file);
directory.setStageStatus(status);
stageDirectoryRepository.save(directory);
}
And this code does not
@Transactional
private void savePassingDirectory(StageDirectory directory) {
Institution institution = institutionRepository.findByActCode(3312);
StageStatus stageStatus = stageStatusRepository.findOne(1L);
// create StageFile reference object
StageFile file = new StageFile();
file.setFileName("3312_DIRECTORY.API");
file.setInstitution(institution);
file.setDeleteFlag('N');
directory.setStageFile(file);
directory.setStageStatus(stageStatus);
stageDirectoryRepository.save(directory);
}