From 15de11de9aafafe787ccb01b4001e5f657fada5c Mon Sep 17 00:00:00 2001 From: Eugene Kovko <37694937+eukovko@users.noreply.github.com> Date: Tue, 23 Jan 2024 19:23:39 +0100 Subject: [PATCH] Bael 7452 updated (#15714) * BAEL-7452: Lazy loaded lists * BAEL-7452: Example with Lazy Lists * BAEL-7452: Test for lazy groups --- .../set/lazy/moderatedomain/Application.java | 8 ++ .../eager/set/lazy/moderatedomain/Group.java | 22 ++++++ .../lazy/moderatedomain/GroupRepository.java | 7 ++ .../set/lazy/moderatedomain/GroupService.java | 29 +++++++ .../eager/set/lazy/moderatedomain/Post.java | 43 +++++++++++ .../lazy/moderatedomain/PostRepository.java | 7 ++ .../eager/set/lazy/moderatedomain/User.java | 45 +++++++++++ .../lazy/moderatedomain/UserRepository.java | 7 ++ .../set/lazy/moderatedomain/UserService.java | 20 +++++ .../lazy/list/moderatedomain/Application.java | 8 ++ .../lazy/list/moderatedomain/Group.java | 22 ++++++ .../list/moderatedomain/GroupRepository.java | 7 ++ .../list/moderatedomain/GroupService.java | 35 +++++++++ .../lazy/list/moderatedomain/Post.java | 23 ++++++ .../list/moderatedomain/PostRepository.java | 7 ++ .../lazy/list/moderatedomain/User.java | 45 +++++++++++ .../list/moderatedomain/UserRepository.java | 7 ++ .../lazy/list/moderatedomain/UserService.java | 20 +++++ .../defaultfetch/list/Application.java | 8 ++ .../nplusone/defaultfetch/list/Post.java | 23 ++++++ .../defaultfetch/list/PostRepository.java | 7 ++ .../nplusone/defaultfetch/list/User.java | 25 ++++++ .../defaultfetch/list/UserRepository.java | 9 +++ .../defaultfetch/list/UserService.java | 20 +++++ ...sOneLazyModerateDomainIntegrationTest.java | 77 +++++++++++++++++++ ...lusOneLazySimpleDomainIntegrationTest.java | 55 +++++++++++++ 26 files changed, 586 insertions(+) create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Application.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Group.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupService.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Post.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/PostRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/User.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserService.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Application.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Group.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupService.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Post.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/PostRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/User.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserService.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Application.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Post.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/PostRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/User.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserRepository.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserService.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazyModerateDomainIntegrationTest.java create mode 100644 persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazySimpleDomainIntegrationTest.java diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Application.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Application.java new file mode 100644 index 0000000000..c9a0442ad6 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Application.java @@ -0,0 +1,8 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Group.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Group.java new file mode 100644 index 0000000000..28e94f542b --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Group.java @@ -0,0 +1,22 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import java.util.Set; +import lombok.Data; + +@Data +@Entity(name = "interest_group") +@Table(name = "interest_group") +public class Group { + + @Id + private Long id; + + private String name; + + @ManyToMany + private Set members; +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupRepository.java new file mode 100644 index 0000000000..8f67f3c10c --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface GroupRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupService.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupService.java new file mode 100644 index 0000000000..9fd9407309 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/GroupService.java @@ -0,0 +1,29 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import java.util.List; +import java.util.Optional; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GroupService { + + private final GroupRepository groupRepository; + + @Autowired + public GroupService(GroupRepository groupRepository) { + this.groupRepository = groupRepository; + } + + public Optional findById(Long aLong) { + return groupRepository.findById(aLong); + } + + public List findAll() { + return groupRepository.findAll(); + } + + public void save(Group group) { + groupRepository.save(group); + } +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Post.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Post.java new file mode 100644 index 0000000000..00edc08e5f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/Post.java @@ -0,0 +1,43 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import java.util.Objects; +import lombok.Data; + +@Entity +@Data +public class Post { + + @Id + private Long id; + + @Lob + private String content; + + @JsonBackReference + @ManyToOne + private User author; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Post post = (Post) o; + + return Objects.equals(id, post.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/PostRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/PostRepository.java new file mode 100644 index 0000000000..8671c4b8a7 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/PostRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/User.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/User.java new file mode 100644 index 0000000000..adb4db8921 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/User.java @@ -0,0 +1,45 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.util.Objects; +import java.util.Set; +import lombok.Data; + +@Data +@Entity(name = "simple_user") +@Table(name = "simple_user") +public class User { + + @Id + private Long id; + private String username; + private String email; + + @JsonManagedReference + @OneToMany(cascade = CascadeType.ALL, mappedBy = "author") + protected Set posts; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + User user = (User) o; + + return Objects.equals(id, user.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserRepository.java new file mode 100644 index 0000000000..93eb21cbf5 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserService.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserService.java new file mode 100644 index 0000000000..d633c55563 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/eager/set/lazy/moderatedomain/UserService.java @@ -0,0 +1,20 @@ +package com.baeldung.listvsset.eager.set.lazy.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@Service +public class UserService extends com.baeldung.listvsset.Service { + + public UserService(JpaRepository repository) { + super(repository); + } + + @Override + public UserRepository getRepository() { + return ((UserRepository) super.getRepository()); + } + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Application.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Application.java new file mode 100644 index 0000000000..4b5c61f89d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Application.java @@ -0,0 +1,8 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Group.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Group.java new file mode 100644 index 0000000000..f74272cb99 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Group.java @@ -0,0 +1,22 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.ManyToMany; +import jakarta.persistence.Table; +import java.util.List; +import lombok.Data; + +@Data +@Entity(name = "interest_group") +@Table(name = "interest_group") +public class Group { + + @Id + private Long id; + + private String name; + + @ManyToMany + private List members; +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupRepository.java new file mode 100644 index 0000000000..2bc919566a --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface GroupRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupService.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupService.java new file mode 100644 index 0000000000..7ee2b83566 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/GroupService.java @@ -0,0 +1,35 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import java.util.List; +import java.util.Optional; +import java.util.function.ToIntFunction; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class GroupService { + + private final GroupRepository groupRepository; + + @Autowired + public GroupService(GroupRepository groupRepository) { + this.groupRepository = groupRepository; + } + + public Optional findById(Long aLong) { + return groupRepository.findById(aLong); + } + + public List findAll() { + return groupRepository.findAll(); + } + public int countNumberOfRequestsWithFunction(ToIntFunction> function) { + return function.applyAsInt(groupRepository.findAll()); + } + + public S save(S entity) { + return groupRepository.save(entity); + } +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Post.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Post.java new file mode 100644 index 0000000000..3d2dc2a89e --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/Post.java @@ -0,0 +1,23 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import lombok.Data; + +@Entity +@Data +public class Post { + + @Id + private Long id; + + @Lob + private String content; + + @JsonBackReference + @ManyToOne + private User author; +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/PostRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/PostRepository.java new file mode 100644 index 0000000000..e1696a9b75 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/PostRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/User.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/User.java new file mode 100644 index 0000000000..d2c19febca --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/User.java @@ -0,0 +1,45 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.util.List; +import java.util.Objects; +import lombok.Data; + +@Data +@Entity(name = "simple_user") +@Table(name = "simple_user") +public class User { + + @Id + private Long id; + private String username; + private String email; + + @JsonManagedReference + @OneToMany(cascade = CascadeType.ALL, mappedBy = "author") + protected List posts; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + User user = (User) o; + + return Objects.equals(id, user.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserRepository.java new file mode 100644 index 0000000000..0a89e1638f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserService.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserService.java new file mode 100644 index 0000000000..22944f5b35 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/listvsset/lazy/list/moderatedomain/UserService.java @@ -0,0 +1,20 @@ +package com.baeldung.listvsset.lazy.list.moderatedomain; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@Service +public class UserService extends com.baeldung.listvsset.Service { + + public UserService(JpaRepository repository) { + super(repository); + } + + @Override + public UserRepository getRepository() { + return ((UserRepository) super.getRepository()); + } + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Application.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Application.java new file mode 100644 index 0000000000..648c153c13 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Application.java @@ -0,0 +1,8 @@ +package com.baeldung.nplusone.defaultfetch.list; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Post.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Post.java new file mode 100644 index 0000000000..b0ad40ec06 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/Post.java @@ -0,0 +1,23 @@ +package com.baeldung.nplusone.defaultfetch.list; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Lob; +import jakarta.persistence.ManyToOne; +import lombok.Data; + +@Entity +@Data +public class Post { + + @Id + private Long id; + + @Lob + private String content; + + @JsonBackReference + @ManyToOne + private User author; +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/PostRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/PostRepository.java new file mode 100644 index 0000000000..19cd9a32bd --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/PostRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.nplusone.defaultfetch.list; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/User.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/User.java new file mode 100644 index 0000000000..81b570a292 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/User.java @@ -0,0 +1,25 @@ +package com.baeldung.nplusone.defaultfetch.list; + +import com.fasterxml.jackson.annotation.JsonManagedReference; +import jakarta.persistence.CascadeType; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.OneToMany; +import jakarta.persistence.Table; +import java.util.List; +import lombok.Data; + +@Data +@Entity(name = "simple_user") +@Table(name = "simple_user") +public class User { + + @Id + private Long id; + private String username; + private String email; + + @JsonManagedReference + @OneToMany(cascade = CascadeType.ALL, mappedBy = "author") + protected List posts; +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserRepository.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserRepository.java new file mode 100644 index 0000000000..22516cd31b --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.nplusone.defaultfetch.list; + +import org.springframework.context.annotation.Lazy; +import org.springframework.data.jpa.repository.JpaRepository; + +@Lazy(value = false) +public interface UserRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserService.java b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserService.java new file mode 100644 index 0000000000..d0decf9f9d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/main/java/com/baeldung/nplusone/defaultfetch/list/UserService.java @@ -0,0 +1,20 @@ +package com.baeldung.nplusone.defaultfetch.list; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Transactional +@Service +public class UserService extends com.baeldung.listvsset.Service { + + public UserService(JpaRepository repository) { + super(repository); + } + + @Override + public UserRepository getRepository() { + return ((UserRepository) super.getRepository()); + } + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazyModerateDomainIntegrationTest.java b/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazyModerateDomainIntegrationTest.java new file mode 100644 index 0000000000..2544a73b24 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazyModerateDomainIntegrationTest.java @@ -0,0 +1,77 @@ +package com.baeldung.listvsset.lazy.list; + +import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount; +import static org.assertj.core.api.Assertions.assertThat; + +import com.baeldung.listvsset.BaseNPlusOneIntegrationTest; +import com.baeldung.listvsset.lazy.list.moderatedomain.Application; +import com.baeldung.listvsset.lazy.list.moderatedomain.Group; +import com.baeldung.listvsset.lazy.list.moderatedomain.GroupService; +import com.baeldung.listvsset.lazy.list.moderatedomain.User; +import com.baeldung.listvsset.util.TestConfig; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = { + "hibernate.show_sql=true", + "logging.level.org.hibernate.SQL=debug", + "logging.level.org.hibernate.orm.jdbc.bind=trace" +}) +class NPlusOneLazyModerateDomainIntegrationTest extends BaseNPlusOneIntegrationTest { + + @Autowired + private GroupService groupService; + + @Test + void givenLazyListBasedUser_whenFetchingAllUsers_thenIssueOneRequest() { + getService().findAll(); + assertSelectCount(1); + } + + @ParameterizedTest + @ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + void givenLazyListBasedUser_whenFetchingOneUser_thenIssueOneRequest(Long id) { + getService().getUserById(id); + assertSelectCount(1); + } + + @Test + void givenLazyListBasedGroup_whenFetchingAllGroups_thenIssueOneRequest() { + groupService.findAll(); + assertSelectCount(1); + } + @Test + void givenLazyListBasedGroup_whenFilteringGroups_thenIssueNPlusOneRequests() { + int numberOfRequests = groupService.countNumberOfRequestsWithFunction(groups -> { + groups.stream() + .map(Group::getMembers) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + return groups.size(); + }); + assertSelectCount(numberOfRequests + 1); + } + + @ParameterizedTest + @ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + void givenLazyListBasedGroup_whenFetchingAllGroups_thenIssueOneRequest(Long groupId) { + Optional group = groupService.findById(groupId); + assertThat(group).isPresent(); + assertSelectCount(1); + } + + protected void addUsers() { + List users = jsonUtils.getUsers(User.class); + databaseUtil.saveAll(users); + List groups = jsonUtils.getGroupsWithMembers(Group.class); + databaseUtil.saveAll(groups); + } + +} diff --git a/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazySimpleDomainIntegrationTest.java b/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazySimpleDomainIntegrationTest.java new file mode 100644 index 0000000000..5d61b76d5d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/src/test/java/com/baeldung/listvsset/lazy/list/NPlusOneLazySimpleDomainIntegrationTest.java @@ -0,0 +1,55 @@ +package com.baeldung.listvsset.lazy.list; + +import static com.vladmihalcea.sql.SQLStatementCountValidator.assertSelectCount; + +import com.baeldung.listvsset.BaseNPlusOneIntegrationTest; +import com.baeldung.listvsset.util.TestConfig; +import com.baeldung.nplusone.defaultfetch.list.Application; +import com.baeldung.nplusone.defaultfetch.list.Post; +import com.baeldung.nplusone.defaultfetch.list.User; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest(classes = {Application.class, TestConfig.class}, properties = { + "hibernate.show_sql=true", + "logging.level.org.hibernate.SQL=debug", + "logging.level.org.hibernate.orm.jdbc.bind=trace" +}) +class NPlusOneLazySimpleDomainIntegrationTest extends BaseNPlusOneIntegrationTest { + + @Test + void givenLazyListBasedUser_WhenFetchingAllUsers_ThenIssueOneRequests() { + getService().findAll(); + assertSelectCount(1); + } + + @Test + void givenLazyListBasedUser_WhenFetchingAllUsersCheckingPosts_ThenIssueNPlusOneRequests() { + int numberOfRequests = getService().countNumberOfRequestsWithFunction(users -> { + List> usersWithPosts + = users.stream() + .map(User::getPosts) + .filter(List::isEmpty) + .toList(); + return users.size(); + }); + assertSelectCount(numberOfRequests + 1); + } + + @ParameterizedTest + @ValueSource(longs = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) + void givenLazyListBasedUser_WhenFetchingOneUser_ThenIssueTwoRequest(Long id) { + getService().getUserByIdWithPredicate(id, user -> !user.getPosts().isEmpty()); + assertSelectCount(2); + } + + + protected void addUsers() { + List users = jsonUtils.getUsers(User.class); + databaseUtil.saveAll(users); + } + +}