javaspringspring-bootjpatransactions

Why doesn't Java Spring Data JPA return nested entities after creation in same request


I'm writing a Java spring boot/spring data REST application.

I have an entity named LabPanel, and an entity named LabResult.

LabPabel contains a @OneToMany relationship with LabResult, so LabResult.labPanelResults is a List<LabResult>.

I have a JPA @Repository interface for LabPanel, and a separate JPA @Repository interface for LabResult.

I have a @Service named LabPanelService, within it is a method named createLabPanel() that lets you create a new LabPanel, and the list of LabResults that it contains.

The problem I'm having occurs when I make a request to createLabPanel().

In the method I create both the LabPanel and all the LabResults, saving them to their respective repositories, then it calls the LabPanelRepository.getOne() interface method to get the new LabPanel after I saved everything to return it to the user.

The result returned to the user shows that the new LabPanel was created, but it shows the LabResult.labPanelResults property is an empty list.

However, if the user then makes a new request to the LabPanelService.getLabPanel method, it then returns the new LabPanel with the LabResult.labPanelResults property populated with the new LabResults.

Since the subsequent request has the nested LabResults, I suspect something is going wrong related to my transaction management, but I don't know what.

I have annotated my LabPanelService methods with @Transactional, and I have annotated my application entry point class with @EnableTransactionManagement.

My code is below (note: I am using Lombok to automatically generate my setters, getters, and constructor methods in my entity classes):

Application entry point

@SpringBootApplication
@EnableTransactionManagement
public class PersonalHealthRecordWebappApplication {

  public static void main(String[] args) {
    SpringApplication.run(PersonalHealthRecordWebappApplication.class, args);
  }
}

LabPanel (entity)

@Entity(name = "lab_panel")
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
public class LabPanel {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  ...

  @OneToMany(mappedBy = "labPanel", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
  private List<LabResult> labPanelResults;

  @ManyToOne
  @JoinColumn(name = "patient_id")
  private Patient patient;
}

LabResult (entity)

@Entity(name = "lab_result")
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Builder
public class LabResult {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id;

  ...

  @ManyToOne
  @JoinColumn(name = "lab_panel_id")
  private LabPanel labPanel;

  @ManyToOne
  @JoinColumn(name = "patient_id")
  private Patient patient;
}

LabPanelRepository

@Repository
public interface LabPanelRepository extends JpaRepository<LabPanel, Long> {
  ...
}

LabResultRepository

@Repository
public interface LabResultRepository extends JpaRepository<LabResult, Long> {
  ...
}

LabPanelService

@Service
public class LabPanelService {

  private final LabPanelRepository labPanelRepository;
  private final LabResultRepository labResultRepository;

  public LabPanelService(
    LabPanelRepository labPanelRepository,
    LabResultRepository labResultRepository
  ) {
    this.labPanelRepository = labPanelRepository;
    this.labResultRepository = labResultRepository;
  }

  ...

  @Transactional
  public LabPanelDTO createLabPanel(
    NewLabPanelRequestDTO newLabPanelRequestDTO
  ) {
    ...

    LabPanel newLabPanel = LabPanel.builder()
      .labPanelUuid(UUID.randomUUID())
      .labPanelName(newLabPanelRequestDTO.getLabPanelName())
      .labPanelDate(newLabPanelRequestDTO.labPanelDate)
      .labPanelResults(new ArrayList<>())
      .patient(patient)
      .build();

    LabPanel savedLabPanel = labPanelRepository.save(newLabPanel);

    List<LabResult> newLabResultList = new ArrayList<>();

    newLabPanelRequestDTO
      .getLabResultsList()
      .forEach(labResultRequestDTO -> {
        LabResult newLabResult = LabResult.builder()
          ...
          .patient(patient)
          .labPanel(savedLabPanel)
          .build();

        newLabResultList.add(newLabResult);
      });

    labResultRepository.saveAll(newLabResultList);
    labResultRepository.flush();

    LabPanel updatedLabPanel = labPanelRepository.getOne(savedLabPanel.getId());

    return ConvertDTOUtil.convertLabPanelToLabPanelDTO(updatedLabPanel);
  }
}

UPDATE:

I ran the application with the logging set to TRACE, and it looks like, after it does the .saveAll() on the list of LabResults to create those, it then executes the .flush(), then does the .getOne() to get the updated LabPanel.

When it does that last step, it retrieves the LabPanel from the session cache instead of querying the database again. I'm not sure if this is what is causing the problem or not.

I am including a section of the logs I have in TRACE mode. The logs I'm including start from right after the labResultRepository.saveAll() method finishes execution, and runs to the closing of the transaction at the end of the entire createLabPanel() method:

2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.saveAll]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@7c9932a2] for key [public abstract java.util.List org.springframework.data.jpa.repository.JpaRepository.saveAll(java.lang.Iterable)] from thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'labPanelRepository'
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@2258d8f8] for key [public abstract void org.springframework.data.jpa.repository.JpaRepository.flush()] to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] toryAnnotationTransactionAttributeSource : Adding transactional method 'org.springframework.data.jpa.repository.support.SimpleJpaRepository.flush' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@301bf7a2] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@15986dd5] bound to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1407529646PersistenceContext[entityKeys=[EntityKey[mh.michael.personal_health_record_webapp.model.LabResult#1], EntityKey[mh.michael.personal_health_record_webapp.model.LabPanel#1], EntityKey[mh.michael.personal_health_record_webapp.model.LabResult#2], EntityKey[mh.michael.personal_health_record_webapp.model.UserRole#1], EntityKey[mh.michael.personal_health_record_webapp.model.Patient#1], EntityKey[mh.michael.personal_health_record_webapp.model.User#1]], collectionKeys=[CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.allergies#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.labResults#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.immunizations#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.users#1], CollectionKey[mh.michael.personal_health_record_webapp.model.User.roles#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.labPanels#1], CollectionKey[mh.michael.personal_health_record_webapp.model.User.patients#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.medications#1]]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@56ef3ef4] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.flush]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@301bf7a2] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@15986dd5] bound to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Flushing session
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Processing flush-time cascades
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.Patient
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.allergies
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.allergies
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.immunizations
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.immunizations
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.labPanels
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.labPanels
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.labResults
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.labResults
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.medications
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.Patient.medications
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.Patient
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.User
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.User
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.UserRole
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.UserRole
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.LabPanel
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.LabPanel.labPanelResults
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done cascade ACTION_PERSIST_ON_FLUSH for collection: mh.michael.personal_health_record_webapp.model.LabPanel.labPanelResults
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.LabPanel
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.LabResult
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.LabResult
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.LabResult
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] org.hibernate.engine.internal.Cascade    : Done processing cascade ACTION_PERSIST_ON_FLUSH for: mh.michael.personal_health_record_webapp.model.LabResult
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Dirty checking collections
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Flushing entities and processing referenced collections
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.Patient.allergies#1], was: [mh.michael.personal_health_record_webapp.model.Patient.allergies#1] (uninitialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.Patient.immunizations#1], was: [mh.michael.personal_health_record_webapp.model.Patient.immunizations#1] (uninitialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.Patient.labPanels#1], was: [mh.michael.personal_health_record_webapp.model.Patient.labPanels#1] (uninitialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.Patient.labResults#1], was: [mh.michael.personal_health_record_webapp.model.Patient.labResults#1] (uninitialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.Patient.medications#1], was: [mh.michael.personal_health_record_webapp.model.Patient.medications#1] (uninitialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.Patient.users#1], was: [mh.michael.personal_health_record_webapp.model.Patient.users#1] (initialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.User.patients#1], was: [mh.michael.personal_health_record_webapp.model.User.patients#1] (initialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.User.roles#1], was: [mh.michael.personal_health_record_webapp.model.User.roles#1] (initialized)
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.engine.internal.Collections  : Collection found: [mh.michael.personal_health_record_webapp.model.LabPanel.labPanelResults#1], was: [<unreferenced>] (initialized)
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Processing unreferenced collections
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Scheduling collection removes/(re)creates/updates
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Flushed: 0 insertions, 0 updates, 0 deletions to 6 objects
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Flushed: 1 (re)creations, 0 updates, 0 removals to 9 collections
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.internal.util.EntityPrinter  : Listing entities:
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.internal.util.EntityPrinter  : mh.michael.personal_health_record_webapp.model.LabResult{labResultValue=50, labResultProviderLocation=null, labResultReferenceRange=30-60, patient=mh.michael.personal_health_record_webapp.model.Patient#1, labResultProviderName=null, labResultName=White Count, labResultUuid=4ab1e1a8-68dd-40ef-ad63-57573054ebce, id=1, labResultNotes=null, labPanel=mh.michael.personal_health_record_webapp.model.LabPanel#1, labResultDate=Mon Jan 01 00:00:00 EST 1990}
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.internal.util.EntityPrinter  : mh.michael.personal_health_record_webapp.model.LabPanel{labPanelResults=[], labPanelDate=Mon Jan 01 00:00:00 EST 1990, patient=mh.michael.personal_health_record_webapp.model.Patient#1, id=1, labPanelName=Complete Metabolic, labPanelUuid=1d364036-b3f1-42d8-8782-31398646a8e2}
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.internal.util.EntityPrinter  : mh.michael.personal_health_record_webapp.model.LabResult{labResultValue=45, labResultProviderLocation=null, labResultReferenceRange=35-66, patient=mh.michael.personal_health_record_webapp.model.Patient#1, labResultProviderName=null, labResultName=Red Count, labResultUuid=237e8edc-a917-457c-a1db-7fc91b108f73, id=2, labResultNotes=null, labPanel=mh.michael.personal_health_record_webapp.model.LabPanel#1, labResultDate=Mon Jan 01 00:00:00 EST 1990}
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.internal.util.EntityPrinter  : mh.michael.personal_health_record_webapp.model.UserRole{name=ROLE_USER, id=1}
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.internal.util.EntityPrinter  : mh.michael.personal_health_record_webapp.model.Patient{allergies=<uninitialized>, patientName=Mike, patientUuid=793f5307-9895-47a3-9f84-02e832a75d8e, immunizations=<uninitialized>, medications=<uninitialized>, labResults=<uninitialized>, id=1, labPanels=<uninitialized>, users=[mh.michael.personal_health_record_webapp.model.User#1]}
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.hibernate.internal.util.EntityPrinter  : mh.michael.personal_health_record_webapp.model.User{password=$2a$10$L6lOJjiT4hpfnydFGo9X4.5G6q8Bk2kU59aDs6EKoweiOcj3Rv5t., patients=[mh.michael.personal_health_record_webapp.model.Patient#1], roles=[mh.michael.personal_health_record_webapp.model.UserRole#1], userUuid=55774c62-81a2-44dd-81f4-1ce3da2ed6a0, id=1, email=mhadjiosif@gmail.com, username=mhadjiosif}
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Executing flush
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.jdbc.internal.JdbcCoordinatorImpl  : Starting after statement execution processing [ON_CLOSE]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.i.AbstractFlushingEventListener    : Post flush
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.flush]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@2258d8f8] for key [public abstract void org.springframework.data.jpa.repository.JpaRepository.flush()] from thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'labPanelRepository'
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@1e1bb812] for key [public abstract java.lang.Object org.springframework.data.jpa.repository.JpaRepository.getOne(java.lang.Object)] to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] toryAnnotationTransactionAttributeSource : Adding transactional method 'org.springframework.data.jpa.repository.support.SimpleJpaRepository.getOne' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@301bf7a2] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@15986dd5] bound to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(1407529646PersistenceContext[entityKeys=[EntityKey[mh.michael.personal_health_record_webapp.model.LabResult#1], EntityKey[mh.michael.personal_health_record_webapp.model.LabPanel#1], EntityKey[mh.michael.personal_health_record_webapp.model.LabResult#2], EntityKey[mh.michael.personal_health_record_webapp.model.UserRole#1], EntityKey[mh.michael.personal_health_record_webapp.model.Patient#1], EntityKey[mh.michael.personal_health_record_webapp.model.User#1]], collectionKeys=[CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.allergies#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.labResults#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.immunizations#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.users#1], CollectionKey[mh.michael.personal_health_record_webapp.model.LabPanel.labPanelResults#1], CollectionKey[mh.michael.personal_health_record_webapp.model.User.roles#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.labPanels#1], CollectionKey[mh.michael.personal_health_record_webapp.model.User.patients#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.medications#1]]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for JPA transaction
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@56ef3ef4] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 DEBUG 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.getOne]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.orm.jpa.EntityManagerHolder@301bf7a2] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@15986dd5] bound to thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.internal.DefaultLoadEventListener  : Loading entity: [mh.michael.personal_health_record_webapp.model.LabPanel#1]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.h.e.internal.DefaultLoadEventListener  : Entity found in session cache
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.getOne]
2025-05-16 01:51:12.648 TRACE 23888 --- [nio-8080-exec-7] .s.t.s.TransactionSynchronizationManager : Removed value [org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$DefaultCrudMethodMetadata@1e1bb812] for key [public abstract java.lang.Object org.springframework.data.jpa.repository.JpaRepository.getOne(java.lang.Object)] from thread [http-nio-8080-exec-7]
2025-05-16 01:51:12.663 TRACE 23888 --- [nio-8080-exec-7] o.s.t.i.TransactionInterceptor           : Completing transaction for [mh.michael.personal_health_record_webapp.services.LabPanelService.createLabPanel]
2025-05-16 01:51:12.664 TRACE 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Triggering beforeCommit synchronization
2025-05-16 01:51:12.664 TRACE 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Triggering beforeCompletion synchronization
2025-05-16 01:51:12.664 DEBUG 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Initiating transaction commit
2025-05-16 01:51:12.664 DEBUG 23888 --- [nio-8080-exec-7] o.s.orm.jpa.JpaTransactionManager        : Committing JPA transaction on EntityManager [SessionImpl(1407529646PersistenceContext[entityKeys=[EntityKey[mh.michael.personal_health_record_webapp.model.LabResult#1], EntityKey[mh.michael.personal_health_record_webapp.model.LabPanel#1], EntityKey[mh.michael.personal_health_record_webapp.model.LabResult#2], EntityKey[mh.michael.personal_health_record_webapp.model.UserRole#1], EntityKey[mh.michael.personal_health_record_webapp.model.Patient#1], EntityKey[mh.michael.personal_health_record_webapp.model.User#1]], collectionKeys=[CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.allergies#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.labResults#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.immunizations#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.users#1], CollectionKey[mh.michael.personal_health_record_webapp.model.LabPanel.labPanelResults#1], CollectionKey[mh.michael.personal_health_record_webapp.model.User.roles#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.labPanels#1], CollectionKey[mh.michael.personal_health_record_webapp.model.User.patients#1], CollectionKey[mh.michael.personal_health_record_webapp.model.Patient.medications#1]]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
2025-05-16 01:51:12.664 DEBUG 23888 --- [nio-8080-exec-7] o.h.e.t.internal.TransactionImpl         : committing

Solution

  • Since you have Cascade all you shoud fill the list in LabPanel with the results and save only LabPanel. Give this a try:

        LabPanel newLabPanel = LabPanel.builder()
                .labPanelUuid(UUID.randomUUID())
                .labPanelName(newLabPanelRequestDTO.getLabPanelName())
                .labPanelDate(newLabPanelRequestDTO.labPanelDate)
                .patient(patient)
                .build();
    
        List<LabResult> newLabResultList = new ArrayList<>();
    
        newLabPanelRequestDTO
                .getLabResultsList()
                .forEach(labResultRequestDTO -> {
                    LabResult newLabResult = LabResult.builder()
          ...
          .patient(patient)
                            .labPanel(newLabPanel)
                            .build();
    
                    newLabResultList.add(newLabResult);
                });
    
        newLabPanel.setLabPanelResults(newLabResultList);
    
        LabPanel savedLabPanel = labPanelRepository.save(newLabPanel);
    
        labPanelRepository.flush();
    
        LabPanel updatedLabPanel = labPanelRepository.getOne(savedLabPanel.getId());
    
        return ConvertDTOUtil.convertLabPanelToLabPanelDTO(updatedLabPanel);
    

    And there should be no need to read the updatedLabPanel again after saving...