From 5a261fa7c6945de9c3dc85145473c0fa3ac4321b Mon Sep 17 00:00:00 2001 From: jinwoo-Bae Date: Sat, 2 Dec 2023 05:06:04 +0900 Subject: [PATCH] Add support for query hints in JPA Item Readers Enhanced `JpaCursorItemReader`, `JpaCursorItemReaderBuilder`, `JpaPagingItemReader`, and `JpaPagingItemReaderBuilder` with query hints configuration. The inclusion of query hints in both cursor and paging item readers improves query execution strategies, optimizing performance for complex data retrieval scenarios. Resolves #4479 --- .../item/database/JpaCursorItemReader.java | 20 ++++++++++++++++++- .../item/database/JpaPagingItemReader.java | 20 ++++++++++++++++++- .../builder/JpaCursorItemReaderBuilder.java | 20 ++++++++++++++++++- .../builder/JpaPagingItemReaderBuilder.java | 19 +++++++++++++++++- 4 files changed, 75 insertions(+), 4 deletions(-) diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java index 89324c5c5..aafdc63ee 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaCursorItemReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,6 +43,7 @@ import org.springframework.util.StringUtils; * The implementation is not thread-safe. * * @author Mahmoud Ben Hassine + * @author Jinwoo Bae * @param type of items to read * @since 4.3 */ @@ -58,6 +59,8 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe private Map parameterValues; + private Map hintValues; + private Iterator iterator; /** @@ -100,6 +103,17 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe this.parameterValues = parameterValues; } + /** + * Set the query hint values for the JPA query. Query hints can be used to give + * instructions to the JPA provider. + * @param hintValues a map where each key is the name of the hint, and the + * corresponding value is the hint's value. + * @since 5.2 + */ + public void setHintValues(Map hintValues) { + this.hintValues = hintValues; + } + @Override public void afterPropertiesSet() throws Exception { Assert.state(this.entityManagerFactory != null, "EntityManagerFactory is required"); @@ -123,6 +137,10 @@ public class JpaCursorItemReader extends AbstractItemCountingItemStreamItemRe if (this.parameterValues != null) { this.parameterValues.forEach(query::setParameter); } + if (this.hintValues != null) { + this.hintValues.forEach(query::setHint); + } + this.iterator = query.getResultStream().iterator(); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java index 1d33e9a6f..d99d3c924 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/JpaPagingItemReader.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2022 the original author or authors. + * Copyright 2006-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,6 +80,7 @@ import org.springframework.util.StringUtils; * @author Dave Syer * @author Will Schipp * @author Mahmoud Ben Hassine + * @author Jinwoo Bae * @since 2.0 */ public class JpaPagingItemReader extends AbstractPagingItemReader { @@ -96,6 +97,8 @@ public class JpaPagingItemReader extends AbstractPagingItemReader { private Map parameterValues; + private Map hintValues; + private boolean transacted = true;// default value public JpaPagingItemReader() { @@ -128,6 +131,17 @@ public class JpaPagingItemReader extends AbstractPagingItemReader { this.parameterValues = parameterValues; } + /** + * Set the query hint values for the JPA query. Query hints can be used to give + * instructions to the JPA provider. + * @param hintValues a map where each key is the name of the hint, and the + * corresponding value is the hint's value. + * @since 5.2 + */ + public void setHintValues(Map hintValues) { + this.hintValues = hintValues; + } + /** * By default (true) the EntityTransaction will be started and committed around the * read. Can be overridden (false) in cases where the JPA implementation doesn't @@ -202,6 +216,10 @@ public class JpaPagingItemReader extends AbstractPagingItemReader { } } + if (this.hintValues != null) { + this.hintValues.forEach(query::setHint); + } + if (results == null) { results = new CopyOnWriteArrayList<>(); } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java index 5a1c874fb..571a5b0a4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaCursorItemReaderBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2021 the original author or authors. + * Copyright 2020-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import org.springframework.util.Assert; * Builder for {@link JpaCursorItemReader}. * * @author Mahmoud Ben Hassine + * @author Jinwoo Bae * @since 4.3 */ public class JpaCursorItemReaderBuilder { @@ -42,6 +43,8 @@ public class JpaCursorItemReaderBuilder { private Map parameterValues; + private Map hintValues; + private boolean saveState = true; private String name; @@ -112,6 +115,19 @@ public class JpaCursorItemReaderBuilder { return this; } + /** + * A map of hint values to be set on the query. The key of the map is the name of the + * hint to be applied, with the value being the specific setting for that hint. + * @param hintValues map of query hints + * @return this instance for method chaining + * @see JpaCursorItemReader#setHintValues(Map) + * @since 5.2 + */ + public JpaCursorItemReaderBuilder hintValues(Map hintValues) { + this.hintValues = hintValues; + return this; + } + /** * A query provider. This should be set only if {@link #queryString(String)} have not * been set. @@ -169,10 +185,12 @@ public class JpaCursorItemReaderBuilder { reader.setQueryProvider(this.queryProvider); reader.setQueryString(this.queryString); reader.setParameterValues(this.parameterValues); + reader.setHintValues(this.hintValues); reader.setCurrentItemCount(this.currentItemCount); reader.setMaxItemCount(this.maxItemCount); reader.setSaveState(this.saveState); reader.setName(this.name); + return reader; } diff --git a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java index adf62a5d8..0bb2a85c4 100644 --- a/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java +++ b/spring-batch-infrastructure/src/main/java/org/springframework/batch/item/database/builder/JpaPagingItemReaderBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2017-2021 the original author or authors. + * Copyright 2017-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -27,6 +27,7 @@ import org.springframework.util.Assert; * * @author Michael Minella * @author Glenn Renfro + * @author Jinwoo Bae * @since 4.0 */ @@ -38,6 +39,8 @@ public class JpaPagingItemReaderBuilder { private Map parameterValues; + private Map hintValues; + private boolean transacted = true; private String queryString; @@ -129,6 +132,19 @@ public class JpaPagingItemReaderBuilder { return this; } + /** + * A map of hint values to be set on the query. The key of the map is the name of the + * hint to be applied, with the value being the specific setting for that hint. + * @param hintValues map of query hints + * @return this instance for method chaining + * @see JpaPagingItemReader#setHintValues(Map) + * @since 5.2 + */ + public JpaPagingItemReaderBuilder hintValues(Map hintValues) { + this.hintValues = hintValues; + return this; + } + /** * A query provider. This should be set only if {@link #queryString(String)} have not * been set. @@ -204,6 +220,7 @@ public class JpaPagingItemReaderBuilder { reader.setQueryString(this.queryString); reader.setPageSize(this.pageSize); reader.setParameterValues(this.parameterValues); + reader.setHintValues(this.hintValues); reader.setEntityManagerFactory(this.entityManagerFactory); reader.setQueryProvider(this.queryProvider); reader.setTransacted(this.transacted);