DATAJPA-1579 - Support multiple out parameters with nullable output data ad hoc stored procedure.

Original pull request: #390.
This commit is contained in:
JyotirmoyVS
2019-07-23 11:44:50 +05:30
committed by Jens Schauder
parent 9c1e0ba645
commit 99d537402b
5 changed files with 43 additions and 11 deletions

View File

@@ -28,6 +28,7 @@ import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.TypedQuery;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -41,6 +42,7 @@ import java.util.stream.IntStream;
* @author Jens Schauder
* @author Mark Paluch
* @author Jeff Sheets
* @author JyotirmoyVS
* @since 1.6
*/
class StoredProcedureJpaQuery extends AbstractJpaQuery {
@@ -110,7 +112,7 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
*
* @param storedProcedureQuery must not be {@literal null}.
* <p>
* Result is either a single value, or a Map<String, Object> of output parameter names to values
* Result is either a single value, or a Map<String, Optional<Object>> of output parameter names to nullable values
*/
@Nullable
Object extractOutputValue(StoredProcedureQuery storedProcedureQuery) {
@@ -121,21 +123,21 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
return null;
}
Map<String, Object> outputValues = IntStream.range(0, procedureAttributes.getOutputParameterNames().size()) //
Map<String, Optional<Object>> outputValues = IntStream.range(0, procedureAttributes.getOutputParameterNames().size()) //
.boxed() //
.collect(Collectors.toMap( //
procedureAttributes.getOutputParameterNames()::get, //
i -> extractOutputParameter(storedProcedureQuery, i)));
return outputValues.size() == 1 ? outputValues.values().iterator().next() : outputValues;
return outputValues.size() == 1 ? outputValues.values().iterator().next().orElse(null) : outputValues;
}
private Object extractOutputParameter(StoredProcedureQuery storedProcedureQuery, Integer index) {
private Optional<Object> extractOutputParameter(StoredProcedureQuery storedProcedureQuery, Integer index) {
String outputParameterName = procedureAttributes.getOutputParameterNames().get(index);
JpaParameters parameters = getQueryMethod().getParameters();
return extractOutputParameterValue(storedProcedureQuery, outputParameterName, index, parameters.getNumberOfParameters());
return Optional.ofNullable(extractOutputParameterValue(storedProcedureQuery, outputParameterName, index, parameters.getNumberOfParameters()));
}
/**

View File

@@ -59,6 +59,7 @@ import javax.persistence.TemporalType;
* @author Christoph Strobl
* @author Jens Schauder
* @author Jeff Sheets
* @author JyotirmoyVS
*/
@Entity
@NamedEntityGraphs({ @NamedEntityGraph(name = "User.overview", attributeNodes = { @NamedAttributeNode("roles") }),
@@ -97,7 +98,11 @@ import javax.persistence.TemporalType;
@NamedStoredProcedureQuery(name = "User.plus1IO2", procedureName = "plus1inout2",
parameters = { @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res2", type = Integer.class) }) //
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res2", type = Integer.class) }), //
@NamedStoredProcedureQuery(name = "User.plus1IOoptional", procedureName = "plus1inoutoptional",
parameters = { @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "res2", type = Integer.class) }) // DATAJPA-1579
})
@NamedStoredProcedureQuery(name = "User.plus1IO", procedureName = "plus1inout",
parameters = { @StoredProcedureParameter(mode = ParameterMode.IN, name = "arg", type = Integer.class),

View File

@@ -29,6 +29,7 @@ import javax.persistence.ParameterMode;
import javax.persistence.PersistenceContext;
import javax.persistence.StoredProcedureQuery;
import java.util.Map;
import java.util.Optional;
import static org.assertj.core.api.Assertions.*;
@@ -39,6 +40,7 @@ import static org.assertj.core.api.Assertions.*;
* @author Oliver Gierke
* @author Jeff Sheets
* @author Jens Schauder
* @author JyotirmoyVS
* @since 1.6
*/
@RunWith(SpringJUnit4ClassRunner.class)
@@ -90,12 +92,20 @@ public class UserRepositoryStoredProcedureIntegrationTests {
assertThat(repository.entityAnnotatedCustomNamedProcedurePlus1IO2TwoOutParamsButNamingOne(1)).isEqualTo(3);
}
@Test // DATAJPA-707
@Test // DATAJPA-707 DATAJPA-1579
public void entityAnnotatedCustomNamedProcedurePlus1IO2() {
Map<String, Integer> result = repository.entityAnnotatedCustomNamedProcedurePlus1IO2(1);
Map<String, Optional<Integer>> result = repository.entityAnnotatedCustomNamedProcedurePlus1IO2(1);
assertThat(result).containsExactly(entry("res", 2), entry("res2", 3));
assertThat(result).containsExactly(entry("res", Optional.of(2)), entry("res2", Optional.of(3)));
}
@Test // DATAJPA-1579
public void entityAnnotatedCustomNamedProcedurePlus1IOoptional() {
Map<String, java.util.Optional<Integer>> result = repository.entityAnnotatedCustomNamedProcedurePlus1IOoptional(1);
assertThat(result).containsExactly(entry("res", Optional.of(2)), entry("res2", Optional.empty()));
}
@Test // DATAJPA-455

View File

@@ -52,6 +52,7 @@ import com.google.common.base.Optional;
* @author Kevin Peters
* @author Jeff Sheets
* @author Andrey Kovalev
* @author JyotirmoyVS
*/
public interface UserRepository
extends JpaRepository<User, Integer>, JpaSpecificationExecutor<User>, UserRepositoryCustom {
@@ -351,8 +352,15 @@ public interface UserRepository
* Explicitly mapped to named stored procedure "User.plus1IO2" in {@link EntityManager}.
* Returns 2 out params as a Map.
*/
@Procedure(name = "User.plus1IO2") // DATAJPA-707
Map<String, Integer> entityAnnotatedCustomNamedProcedurePlus1IO2(@Param("arg") Integer arg);
@Procedure(name = "User.plus1IO2") // DATAJPA-707 DATAJPA-1579
Map<String, java.util.Optional<Integer>> entityAnnotatedCustomNamedProcedurePlus1IO2(@Param("arg") Integer arg);
/**
* Explicitly mapped to named stored procedure "User.plus1IOoptional" in {@link EntityManager}.
* Returns 2 out params as a Map, second one amoung which is null.
*/
@Procedure(name = "User.plus1IOoptional") // DATAJPA-1579
Map<String, java.util.Optional<Integer>> entityAnnotatedCustomNamedProcedurePlus1IOoptional(@Param("arg") Integer arg);
/**
* Implicitly mapped to named stored procedure "User.plus1" in {@link EntityManager}.

View File

@@ -14,6 +14,13 @@ BEGIN ATOMIC
set res2 = arg + 2;
END
/;
DROP procedure IF EXISTS plus1inoutoptional
/;
CREATE procedure plus1inoutoptional (IN arg int, OUT res int, OUT res2 int)
BEGIN ATOMIC
set res = arg + 1;
END
/;
DROP procedure IF EXISTS procedure_in1_out1
/;
DROP procedure IF EXISTS procedure_in1_out0