From f3d21118941801dd0d1794c8bd08395a82da09cf Mon Sep 17 00:00:00 2001 From: Raja Kolli Date: Mon, 6 Jan 2025 02:59:24 +0000 Subject: [PATCH 1/3] sets up infra to load heavy data --- jpa/boot-jpa-jooq-sample/pom.xml | 9 ++- .../com/example/learning/entities/Post.java | 22 +++--- .../com/example/learning/entities/Tag.java | 10 +++ .../learning/repository/PostRepository.java | 6 ++ .../example/learning/utils/AppConstants.java | 6 ++ .../resources/application-local.properties | 3 + .../src/main/resources/application.properties | 15 +++- .../learning/ApplicationIntegrationTest.java | 74 +++++++++++++++++++ .../common/AbstractIntegrationTest.java | 33 +++++++++ .../common/AbstractIntegrationTest.java | 3 +- 10 files changed, 164 insertions(+), 17 deletions(-) create mode 100644 jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/PostRepository.java create mode 100644 jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/utils/AppConstants.java create mode 100644 jpa/boot-jpa-jooq-sample/src/main/resources/application-local.properties create mode 100644 jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java create mode 100644 jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java diff --git a/jpa/boot-jpa-jooq-sample/pom.xml b/jpa/boot-jpa-jooq-sample/pom.xml index f40e9a8e4..fa611f9dc 100644 --- a/jpa/boot-jpa-jooq-sample/pom.xml +++ b/jpa/boot-jpa-jooq-sample/pom.xml @@ -64,7 +64,7 @@ springdoc-openapi-starter-webmvc-ui ${springdoc-openapi.version} - + org.springframework.boot spring-boot-starter-test @@ -85,6 +85,11 @@ postgresql test + + org.instancio + instancio-junit + 5.2.1 + @@ -266,4 +271,4 @@ - \ No newline at end of file + diff --git a/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Post.java b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Post.java index 03a38a86c..4e2d53d3e 100644 --- a/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Post.java +++ b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Post.java @@ -114,6 +114,17 @@ public PostDetails getDetails() { return details; } + public void setDetails(PostDetails details) { + if (details == null) { + if (this.details != null) { + this.details.setPost(null); + } + } else { + details.setPost(this); + } + this.details = details; + } + public List getTags() { return tags; } @@ -148,17 +159,6 @@ public void removeComment(PostComment comment) { comment.setPost(null); } - public void setDetails(PostDetails details) { - if (details == null) { - if (this.details != null) { - this.details.setPost(null); - } - } else { - details.setPost(this); - } - this.details = details; - } - public void addTag(Tag tag) { PostTag postTag = new PostTag(this, tag); this.tags.add(postTag); diff --git a/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Tag.java b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Tag.java index c73ab0d22..453956cc6 100644 --- a/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Tag.java +++ b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/entities/Tag.java @@ -10,6 +10,7 @@ import java.io.Serial; import java.io.Serializable; import java.util.Objects; +import java.util.StringJoiner; @Entity @Table( @@ -58,6 +59,15 @@ public Tag setTagDescription(String tagDescription) { return this; } + @Override + public String toString() { + return new StringJoiner(", ", Tag.class.getSimpleName() + "[", "]") + .add("id=" + id) + .add("tagName='" + tagName + "'") + .add("tagDescription='" + tagDescription + "'") + .toString(); + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/PostRepository.java b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/PostRepository.java new file mode 100644 index 000000000..848d92cee --- /dev/null +++ b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/PostRepository.java @@ -0,0 +1,6 @@ +package com.example.learning.repository; + +import com.example.learning.entities.Post; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository {} diff --git a/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/utils/AppConstants.java b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/utils/AppConstants.java new file mode 100644 index 000000000..6a3f01ff0 --- /dev/null +++ b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/utils/AppConstants.java @@ -0,0 +1,6 @@ +package com.example.learning.utils; + +public interface AppConstants { + + String PROFILE_TEST = "test"; +} diff --git a/jpa/boot-jpa-jooq-sample/src/main/resources/application-local.properties b/jpa/boot-jpa-jooq-sample/src/main/resources/application-local.properties new file mode 100644 index 000000000..6e6853bf1 --- /dev/null +++ b/jpa/boot-jpa-jooq-sample/src/main/resources/application-local.properties @@ -0,0 +1,3 @@ +spring.datasource.url=jdbc:postgresql://localhost:5432/appdb +spring.datasource.username=appuser +spring.datasource.password=secret diff --git a/jpa/boot-jpa-jooq-sample/src/main/resources/application.properties b/jpa/boot-jpa-jooq-sample/src/main/resources/application.properties index b6739de35..70c0b3766 100644 --- a/jpa/boot-jpa-jooq-sample/src/main/resources/application.properties +++ b/jpa/boot-jpa-jooq-sample/src/main/resources/application.properties @@ -3,10 +3,11 @@ server.port=8080 server.shutdown=graceful spring.jmx.enabled=false spring.mvc.problemdetails.enabled=true +spring.threads.virtual.enabled=true ################ Actuator ##################### management.endpoints.web.exposure.include=configprops,env,health,info,logfile,loggers,metrics,prometheus -management.endpoint.health.access=read_only +management.endpoint.health.access=READ_ONLY ################ Database ##################### spring.jpa.show-sql=false @@ -16,7 +17,6 @@ spring.datasource.hikari.auto-commit=false spring.datasource.hikari.pool-name=HikariPool-${spring.application.name} spring.datasource.hikari.data-source-properties.ApplicationName=${spring.application.name} spring.jpa.hibernate.ddl-auto=none -#spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.jdbc.time_zone=UTC spring.jpa.properties.hibernate.generate_statistics=false spring.jpa.properties.hibernate.jdbc.batch_size=25 @@ -27,4 +27,13 @@ spring.jpa.properties.hibernate.query.in_clause_parameter_padding=true spring.jpa.properties.hibernate.query.plan_cache_max_size=4096 spring.jpa.properties.hibernate.connection.provider_disables_autocommit=true spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true -spring.threads.virtual.enabled=true + +jdbc.datasource-proxy.logging=slf4j +jdbc.datasource-proxy.include-parameter-values=true +jdbc.datasource-proxy.query.enable-logging=true +jdbc.datasource-proxy.query.logger-name=query-logger +jdbc.datasource-proxy.slow-query.enable-logging=true +jdbc.datasource-proxy.slow-query.logger-name=slow-query-logger + +logging.level.query-logger=DEBUG +logging.level.slow-query-logger=DEBUG diff --git a/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java new file mode 100644 index 000000000..46b20491a --- /dev/null +++ b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java @@ -0,0 +1,74 @@ +package com.example.learning; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.instancio.Select.all; +import static org.instancio.Select.field; + +import com.example.learning.common.AbstractIntegrationTest; +import com.example.learning.entities.Post; +import com.example.learning.entities.PostComment; +import com.example.learning.entities.PostDetails; +import com.example.learning.entities.PostTag; +import com.example.learning.entities.Tag; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import org.instancio.Instancio; +import org.junit.jupiter.api.Test; + +class ApplicationIntegrationTest extends AbstractIntegrationTest { + + @Test + void contextLoads() { + // Create a finite dataset of tags with unique tag names + List finiteTags = Instancio.ofList(Tag.class) + .size(100) // Limit to 100 unique tags + .ignore(field(Tag::getId)) + .create(); + + // Generate Post objects with specific fields ignored + List postList = Instancio.ofList(Post.class) + .size(100) + .ignore(field(Post::getId)) + .ignore(field(Post::getCreatedAt)) + .ignore(field(Post::getModifiedAt)) + .supply(all(LocalDateTime.class), () -> LocalDateTime.now()) + .supply(field(Post::getDetails), () -> Instancio.of(PostDetails.class) + .ignore(field(PostDetails::getId)) + .ignore(field(PostDetails::getCreatedAt)) + .ignore(field(PostDetails::getModifiedAt)) + .ignore(field(PostDetails::getPost)) + .create()) + .supply(field(Post::getComments), () -> new ArrayList()) + .supply(field(Post::getTags), () -> new ArrayList()) + .create(); + + // Assign tags and comments to posts, reusing finite tags + postList.forEach(post -> { + post.setDetails(post.getDetails()); + + List postCommentList = Instancio.ofList(PostComment.class) + .size(50) // Assuming 50 comments per post + .ignore(field(PostComment::getId)) + .ignore(field(PostComment::getCreatedAt)) + .ignore(field(PostComment::getModifiedAt)) + .ignore(field(PostComment::getPost)) + .create(); + postCommentList.forEach(post::addComment); + + // Randomly select tags from the finiteTags dataset + Collections.shuffle(finiteTags); // Shuffle to randomize selection + List tags = finiteTags.stream() + .limit(30) // Assign 30 tags per post + .toList(); + tags.forEach(post::addTag); + }); + + // Save the modified posts + List savedPostList = postRepository.saveAll(postList); + + // Assertions to validate the results + assertThat(savedPostList).isNotEmpty().hasSize(postList.size()); + } +} diff --git a/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java new file mode 100644 index 000000000..ed405b432 --- /dev/null +++ b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java @@ -0,0 +1,33 @@ +package com.example.learning.common; + +import static com.example.learning.utils.AppConstants.PROFILE_TEST; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +import com.example.learning.repository.PostRepository; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.instancio.junit.InstancioExtension; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.assertj.MockMvcTester; + +@ActiveProfiles({PROFILE_TEST}) +@SpringBootTest( + webEnvironment = RANDOM_PORT, + classes = {SQLContainerConfig.class}, + properties = {"jdbc.datasource-proxy.enabled=false"}) +@AutoConfigureMockMvc +@ExtendWith(InstancioExtension.class) +public abstract class AbstractIntegrationTest { + + @Autowired + protected MockMvcTester mockMvcTester; + + @Autowired + protected ObjectMapper objectMapper; + + @Autowired + protected PostRepository postRepository; +} diff --git a/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java b/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java index cab2797ac..74d0a7e34 100644 --- a/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java +++ b/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java @@ -24,7 +24,8 @@ @ActiveProfiles({PROFILE_TEST}) @SpringBootTest( webEnvironment = RANDOM_PORT, - classes = {ContainersConfig.class}) + classes = {ContainersConfig.class}, + properties = {"jdbc.datasource-proxy.enabled=false"})) @AutoConfigureMockMvc public abstract class AbstractIntegrationTest { From a8633631c36030234dbe7d9ef79add85c9dd6a10 Mon Sep 17 00:00:00 2001 From: Raja Kolli Date: Mon, 6 Jan 2025 03:00:02 +0000 Subject: [PATCH 2/3] fix typo --- .../keysetpagination/common/AbstractIntegrationTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java b/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java index 74d0a7e34..ffd042ef1 100644 --- a/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java +++ b/jpa/keyset-pagination/boot-data-window-pagination/src/test/java/com/example/keysetpagination/common/AbstractIntegrationTest.java @@ -25,7 +25,7 @@ @SpringBootTest( webEnvironment = RANDOM_PORT, classes = {ContainersConfig.class}, - properties = {"jdbc.datasource-proxy.enabled=false"})) + properties = {"jdbc.datasource-proxy.enabled=false"}) @AutoConfigureMockMvc public abstract class AbstractIntegrationTest { From 30b656002df731883cfe7c504cfcb3372414e3b7 Mon Sep 17 00:00:00 2001 From: Raja Kolli Date: Mon, 6 Jan 2025 03:20:46 +0000 Subject: [PATCH 3/3] adds more assertions --- .../java/com/example/learning/repository/TagRepository.java | 6 ++++++ .../com/example/learning/ApplicationIntegrationTest.java | 1 + .../example/learning/common/AbstractIntegrationTest.java | 4 ++++ 3 files changed, 11 insertions(+) create mode 100644 jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/TagRepository.java diff --git a/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/TagRepository.java b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/TagRepository.java new file mode 100644 index 000000000..faa7a4fc0 --- /dev/null +++ b/jpa/boot-jpa-jooq-sample/src/main/java/com/example/learning/repository/TagRepository.java @@ -0,0 +1,6 @@ +package com.example.learning.repository; + +import com.example.learning.entities.Tag; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TagRepository extends JpaRepository {} diff --git a/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java index 46b20491a..44177adc2 100644 --- a/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java +++ b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/ApplicationIntegrationTest.java @@ -70,5 +70,6 @@ void contextLoads() { // Assertions to validate the results assertThat(savedPostList).isNotEmpty().hasSize(postList.size()); + assertThat(tagRepository.count()).isEqualTo(100); } } diff --git a/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java index ed405b432..a42c66ee0 100644 --- a/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java +++ b/jpa/boot-jpa-jooq-sample/src/test/java/com/example/learning/common/AbstractIntegrationTest.java @@ -4,6 +4,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import com.example.learning.repository.PostRepository; +import com.example.learning.repository.TagRepository; import com.fasterxml.jackson.databind.ObjectMapper; import org.instancio.junit.InstancioExtension; import org.junit.jupiter.api.extension.ExtendWith; @@ -30,4 +31,7 @@ public abstract class AbstractIntegrationTest { @Autowired protected PostRepository postRepository; + + @Autowired + protected TagRepository tagRepository; }