From 5c2d7f23f53b1c29daf8a3d931645790290891ad Mon Sep 17 00:00:00 2001 From: Mickael-7 Date: Sun, 7 Dec 2025 18:01:45 -0300 Subject: [PATCH] feat: optimize JPA performance with lazy loading and fetch joins Signed-off-by: Mickael-7 --- .../org/springframework/samples/petclinic/owner/Owner.java | 2 +- .../samples/petclinic/owner/OwnerRepository.java | 2 ++ .../java/org/springframework/samples/petclinic/owner/Pet.java | 2 +- .../java/org/springframework/samples/petclinic/vet/Vet.java | 2 +- .../springframework/samples/petclinic/vet/VetRepository.java | 3 +++ 5 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java index 715863cd2..6f28c97ce 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/Owner.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/Owner.java @@ -61,7 +61,7 @@ public class Owner extends Person { @Pattern(regexp = "\\d{10}", message = "{telephone.invalid}") private String telephone; - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "owner_id") @OrderBy("name") private final List pets = new ArrayList<>(); diff --git a/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java b/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java index d2b3dde40..e6f0df835 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/OwnerRepository.java @@ -20,6 +20,7 @@ import java.util.Optional; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; /** * Repository class for Owner domain objects. All method names are compliant @@ -57,6 +58,7 @@ public interface OwnerRepository extends JpaRepository { * @throws IllegalArgumentException if the id is null (assuming null is not a valid * input for id) */ + @Query("SELECT DISTINCT owner FROM Owner owner LEFT JOIN FETCH owner.pets p LEFT JOIN FETCH p.visits WHERE owner.id = :id") Optional findById(Integer id); } diff --git a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java index 1945f9b67..bfac2680c 100644 --- a/src/main/java/org/springframework/samples/petclinic/owner/Pet.java +++ b/src/main/java/org/springframework/samples/petclinic/owner/Pet.java @@ -53,7 +53,7 @@ public class Pet extends NamedEntity { @JoinColumn(name = "type_id") private PetType type; - @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "pet_id") @OrderBy("date ASC") private final Set visits = new LinkedHashSet<>(); diff --git a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java index fb2bd71ee..bb7721b79 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/Vet.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/Vet.java @@ -44,7 +44,7 @@ import jakarta.xml.bind.annotation.XmlElement; @Table(name = "vets") public class Vet extends Person { - @ManyToMany(fetch = FetchType.EAGER) + @ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "vet_specialties", joinColumns = @JoinColumn(name = "vet_id"), inverseJoinColumns = @JoinColumn(name = "specialty_id")) private Set specialties; diff --git a/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java index dbf68d029..9b9ad0e3e 100644 --- a/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java +++ b/src/main/java/org/springframework/samples/petclinic/vet/VetRepository.java @@ -19,6 +19,7 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.dao.DataAccessException; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.Repository; import org.springframework.transaction.annotation.Transactional; @@ -41,6 +42,7 @@ public interface VetRepository extends Repository { * Retrieve all Vets from the data store. * @return a Collection of Vets */ + @Query("SELECT DISTINCT vet FROM Vet vet LEFT JOIN FETCH vet.specialties") @Transactional(readOnly = true) @Cacheable("vets") Collection findAll() throws DataAccessException; @@ -51,6 +53,7 @@ public interface VetRepository extends Repository { * @return * @throws DataAccessException */ + @Query("SELECT DISTINCT vet FROM Vet vet LEFT JOIN FETCH vet.specialties") @Transactional(readOnly = true) @Cacheable("vets") Page findAll(Pageable pageable) throws DataAccessException;