Skip to content

Commit

Permalink
Store the position of each output parameter in ProcedureParameter so …
Browse files Browse the repository at this point in the history
…that it can be used when extracting them from the result set. This fixes issue 3460.
  • Loading branch information
thjanssen committed May 4, 2024
1 parent 61bc6bd commit 5e19dba
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
class ProcedureParameter {

private final String name;
private final int position;
private final ParameterMode mode;
private final Class<?> type;

ProcedureParameter(@Nullable String name, ParameterMode mode, Class<?> type) {
ProcedureParameter(@Nullable String name, int position, ParameterMode mode, Class<?> type) {

this.name = name;
this.position = position;
this.mode = mode;
this.type = type;
}
Expand All @@ -46,6 +48,10 @@ public String getName() {
return name;
}

public int getPosition() {
return position;
}

public ParameterMode getMode() {
return mode;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,7 @@ private StoredProcedureAttributes newProcedureAttributesFrom(Method method, Name
} else {

// try to discover the output parameter
outputParameters = extractOutputParametersFrom(namedStoredProc).stream() //
.map(namedParameter -> new ProcedureParameter(namedParameter.name(), namedParameter.mode(),
namedParameter.type())) //
.collect(Collectors.toList());
outputParameters = extractOutputParametersFrom(namedStoredProc);
}

return new StoredProcedureAttributes(namedStoredProc.name(), outputParameters, true);
Expand All @@ -137,33 +134,36 @@ private StoredProcedureAttributes newProcedureAttributesFrom(Method method, Name
*/
private ProcedureParameter createOutputProcedureParameterFrom(Method method, Procedure procedure) {

return new ProcedureParameter(procedure.outputParameterName(),
return new ProcedureParameter(procedure.outputParameterName(), 1,
procedure.refCursor() ? ParameterMode.REF_CURSOR : ParameterMode.OUT, method.getReturnType());
}

/**
* Translate all the {@Link NamedStoredProcedureQuery} parameters into a {@link List} of
* {@link StoredProcedureParameter}s.
* {@link ProcedureParameter}s.
*
* @param namedStoredProc
* @return
*/
private List<StoredProcedureParameter> extractOutputParametersFrom(NamedStoredProcedureQuery namedStoredProc) {
private List<ProcedureParameter> extractOutputParametersFrom(NamedStoredProcedureQuery namedStoredProc) {

List<StoredProcedureParameter> outputParameters = new ArrayList<>();
List<ProcedureParameter> outputParameters = new ArrayList<>();

int position = 1;
for (StoredProcedureParameter param : namedStoredProc.parameters()) {

switch (param.mode()) {
case OUT:
case INOUT:
case REF_CURSOR:
outputParameters.add(param);
outputParameters.add(new ProcedureParameter(param.name(), position, param.mode(), param.type()));
break;
case IN:
default:
continue;
// not an output parameter
}

position++;
}

return outputParameters;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private List<ProcedureParameter> getParametersWithCompletedNames(List<ProcedureP

private ProcedureParameter getParameterWithCompletedName(ProcedureParameter parameter, int i) {

return new ProcedureParameter(completeOutputParameterName(i, parameter.getName()), parameter.getMode(),
return new ProcedureParameter(completeOutputParameterName(i, parameter.getName()), i+1, parameter.getMode(),
parameter.getType());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@ Object extractOutputValue(StoredProcedureQuery storedProcedureQuery) {
List<ProcedureParameter> outputParameters = procedureAttributes.getOutputProcedureParameters();

if (outputParameters.size() == 1) {
return extractOutputParameterValue(outputParameters.get(0), 0, storedProcedureQuery);
return extractOutputParameterValue(outputParameters.get(0), storedProcedureQuery);
}

Map<String, Object> outputValues = new HashMap<>();

for (int i = 0; i < outputParameters.size(); i++) {
ProcedureParameter outputParameter = outputParameters.get(i);
outputValues.put(outputParameter.getName(),
extractOutputParameterValue(outputParameter, i, storedProcedureQuery));
outputValues.put(!outputParameter.getName().isEmpty() ? outputParameter.getName() : outputParameter.getPosition()+"",
extractOutputParameterValue(outputParameter, storedProcedureQuery));
}

return outputValues;
Expand All @@ -136,14 +136,12 @@ Object extractOutputValue(StoredProcedureQuery storedProcedureQuery) {
/**
* @return The value of an output parameter either by name or by index.
*/
private Object extractOutputParameterValue(ProcedureParameter outputParameter, Integer index,
private Object extractOutputParameterValue(ProcedureParameter outputParameter,
StoredProcedureQuery storedProcedureQuery) {

JpaParameters methodParameters = getQueryMethod().getParameters();

return useNamedParameters && StringUtils.hasText(outputParameter.getName())
? storedProcedureQuery.getOutputParameterValue(outputParameter.getName())
: storedProcedureQuery.getOutputParameterValue(methodParameters.getNumberOfParameters() + index + 1);
: storedProcedureQuery.getOutputParameterValue(outputParameter.getPosition());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;

Expand Down Expand Up @@ -152,11 +153,11 @@ void testEntityListFromNamedProcedure() {
@Test // 3460
void testPositionalInOutParameter() {

Object[] results = repository.positionalInOut(1, 2);
Map results = repository.positionalInOut(1, 2);

assertThat(results).containsExactly( //
2, //
3);
// TODO: Check result format
assertThat(results.get("2")).isEqualTo(2);
assertThat(results.get("3")).isEqualTo(3);
}

@Entity
Expand Down Expand Up @@ -252,7 +253,7 @@ public interface EmployeeRepositoryWithRefCursor extends JpaRepository<Employee,
List<Employee> entityListFromNamedProcedure();

@Procedure(name = "positional_inout")
Object[] positionalInOut(Integer in, Integer inout);
Map positionalInOut(Integer in, Integer inout);
}

@EnableJpaRepositories(considerNestedRepositories = true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class StoredProcedureAttributesUnitTests {
void usesSyntheticOutputParameterNameForAdhocProcedureWithoutOutputName() {

StoredProcedureAttributes attributes = new StoredProcedureAttributes("procedure",
new ProcedureParameter(null, ParameterMode.OUT, Long.class));
new ProcedureParameter(null, 1, ParameterMode.OUT, Long.class));
assertThat(attributes.getOutputProcedureParameters().get(0).getName()).isEqualTo(SYNTHETIC_OUTPUT_PARAMETER_NAME);
}
}

0 comments on commit 5e19dba

Please sign in to comment.