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
This commit is contained in:
jinwoo-Bae
2023-12-02 05:06:04 +09:00
committed by Mahmoud Ben Hassine
parent d1bd7711c3
commit 5a261fa7c6
4 changed files with 75 additions and 4 deletions

View File

@@ -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 <b>not</b> thread-safe.
*
* @author Mahmoud Ben Hassine
* @author Jinwoo Bae
* @param <T> type of items to read
* @since 4.3
*/
@@ -58,6 +59,8 @@ public class JpaCursorItemReader<T> extends AbstractItemCountingItemStreamItemRe
private Map<String, Object> parameterValues;
private Map<String, Object> hintValues;
private Iterator<T> iterator;
/**
@@ -100,6 +103,17 @@ public class JpaCursorItemReader<T> 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<String, Object> 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<T> 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();
}

View File

@@ -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<T> extends AbstractPagingItemReader<T> {
@@ -96,6 +97,8 @@ public class JpaPagingItemReader<T> extends AbstractPagingItemReader<T> {
private Map<String, Object> parameterValues;
private Map<String, Object> hintValues;
private boolean transacted = true;// default value
public JpaPagingItemReader() {
@@ -128,6 +131,17 @@ public class JpaPagingItemReader<T> extends AbstractPagingItemReader<T> {
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<String, Object> 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<T> extends AbstractPagingItemReader<T> {
}
}
if (this.hintValues != null) {
this.hintValues.forEach(query::setHint);
}
if (results == null) {
results = new CopyOnWriteArrayList<>();
}

View File

@@ -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<T> {
@@ -42,6 +43,8 @@ public class JpaCursorItemReaderBuilder<T> {
private Map<String, Object> parameterValues;
private Map<String, Object> hintValues;
private boolean saveState = true;
private String name;
@@ -112,6 +115,19 @@ public class JpaCursorItemReaderBuilder<T> {
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<T> hintValues(Map<String, Object> 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<T> {
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;
}

View File

@@ -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<T> {
private Map<String, Object> parameterValues;
private Map<String, Object> hintValues;
private boolean transacted = true;
private String queryString;
@@ -129,6 +132,19 @@ public class JpaPagingItemReaderBuilder<T> {
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<T> hintValues(Map<String, Object> 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<T> {
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);