Polishing.

See: #1959, #409.
This commit is contained in:
Greg L. Turnquist
2021-07-09 11:05:25 -05:00
parent 554bd3d6ed
commit 0a81bc6a5d
11 changed files with 193 additions and 109 deletions

18
pom.xml
View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -101,7 +102,9 @@
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.artifactId}-${project.version}.zip</file>
<file>
${project.build.directory}/${project.artifactId}-${project.version}.zip
</file>
<type>zip</type>
</artifact>
</artifacts>
@@ -358,7 +361,10 @@
<exclude>**/OpenJpa*</exclude>
<exclude>**/EclipseLink*</exclude>
</excludes>
<argLine>-javaagent:${settings.localRepository}/org/springframework/spring-instrument/${spring}/spring-instrument-${spring}.jar -javaagent:${settings.localRepository}/org/jacoco/org.jacoco.agent/${jacoco}/org.jacoco.agent-${jacoco}-runtime.jar=destfile=${jacoco.destfile}</argLine>
<argLine>
-javaagent:${settings.localRepository}/org/springframework/spring-instrument/${spring}/spring-instrument-${spring}.jar
-javaagent:${settings.localRepository}/org/jacoco/org.jacoco.agent/${jacoco}/org.jacoco.agent-${jacoco}-runtime.jar=destfile=${jacoco.destfile}
</argLine>
</configuration>
</execution>
<execution>
@@ -371,7 +377,11 @@
<includes>
<include>**/EclipseLink*Tests.java</include>
</includes>
<argLine>-javaagent:${settings.localRepository}/org/jacoco/org.jacoco.agent/${jacoco}/org.jacoco.agent-${jacoco}-runtime.jar=destfile=${jacoco.destfile} -javaagent:${settings.localRepository}/org/eclipse/persistence/org.eclipse.persistence.jpa/${eclipselink}/org.eclipse.persistence.jpa-${eclipselink}.jar -javaagent:${settings.localRepository}/org/springframework/spring-instrument/${spring}/spring-instrument-${spring}.jar</argLine>
<argLine>
-javaagent:${settings.localRepository}/org/jacoco/org.jacoco.agent/${jacoco}/org.jacoco.agent-${jacoco}-runtime.jar=destfile=${jacoco.destfile}
-javaagent:${settings.localRepository}/org/eclipse/persistence/org.eclipse.persistence.jpa/${eclipselink}/org.eclipse.persistence.jpa-${eclipselink}.jar
-javaagent:${settings.localRepository}/org/springframework/spring-instrument/${spring}/spring-instrument-${spring}.jar
</argLine>
</configuration>
</execution>
</executions>

View File

@@ -54,6 +54,7 @@ import org.springframework.util.ReflectionUtils;
* @author Nicolas Cirigliano
* @author Jens Schauder
* @author Gabriel Basilio
* @author Greg Turnquist
*/
public abstract class JpaQueryExecution {
@@ -319,19 +320,16 @@ public abstract class JpaQueryExecution {
boolean returnsResultSet = storedProcedure.execute();
if (returnsResultSet) {
if (!SurroundingTransactionDetectorMethodInterceptor.INSTANCE.isSurroundingTransactionActive())
if (!SurroundingTransactionDetectorMethodInterceptor.INSTANCE.isSurroundingTransactionActive()) {
throw new InvalidDataAccessApiUsageException(NO_SURROUNDING_TRANSACTION);
List<?> result = storedProcedure.getResultList();
if (!storedProcedureJpaQuery.getQueryMethod().isCollectionQuery()) {
if (result.isEmpty())
return null;
if (result.size() == 1)
return result.get(0);
}
return result;
if (storedProcedureJpaQuery.getQueryMethod().isCollectionQuery()) {
return storedProcedure.getResultList();
} else {
return storedProcedure.getSingleResult();
}
}
return storedProcedureJpaQuery.extractOutputValue(storedProcedure);

View File

@@ -54,7 +54,7 @@ public @interface Procedure {
String outputParameterName() default "";
/**
* Whether the procedure returns a Ref Cursor from the database {@code false}.
* Whether the procedure returns a Ref Cursor from the database - defaults to {@code false}.
*/
boolean refCursor() default false;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2020 the original author or authors.
* Copyright 2021 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.
@@ -16,23 +16,27 @@
package org.springframework.data.jpa.repository.query;
import org.springframework.lang.Nullable;
import java.util.Objects;
import javax.persistence.ParameterMode;
import org.springframework.lang.Nullable;
/**
* This class represents a Stored Procedure Parameter
* and an instance of the annotation {@link javax.persistence.StoredProcedureParameter}.
* This class represents a Stored Procedure Parameter and an instance of the annotation
* {@link javax.persistence.StoredProcedureParameter}.
*
* @author Gabriel Basilio
* @author Greg Turnquist
*/
public class ProcedureParameter {
class ProcedureParameter {
private final String name;
private final ParameterMode mode;
private final Class<?> type;
public ProcedureParameter(@Nullable String name, ParameterMode mode, Class<?> type) {
ProcedureParameter(@Nullable String name, ParameterMode mode, Class<?> type) {
this.name = name;
this.mode = mode;
this.type = type;
@@ -49,4 +53,29 @@ public class ProcedureParameter {
public Class<?> getType() {
return type;
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof ProcedureParameter)) {
return false;
}
ProcedureParameter that = (ProcedureParameter) o;
return Objects.equals(name, that.name) && mode == that.mode && Objects.equals(type, that.type);
}
@Override
public int hashCode() {
return Objects.hash(name, mode, type);
}
@Override
public String toString() {
return "ProcedureParameter{" + "name='" + name + '\'' + ", mode=" + mode + ", type=" + type + '}';
}
}

View File

@@ -18,7 +18,9 @@ package org.springframework.data.jpa.repository.query;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery;
@@ -28,6 +30,7 @@ import javax.persistence.StoredProcedureParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -40,6 +43,7 @@ import org.springframework.util.StringUtils;
* @author Diego Diez
* @author Jeff Sheets
* @author Gabriel Basilio
* @author Greg Turnquist
* @since 1.6
*/
enum StoredProcedureAttributeSource {
@@ -69,9 +73,9 @@ enum StoredProcedureAttributeSource {
}
String procedureName = deriveProcedureNameFrom(method, procedure);
if (StringUtils.isEmpty(procedureName)) {
throw new IllegalArgumentException("Could not determine name of procedure for @Procedure annotated method: "
+ method);
if (ObjectUtils.isEmpty(procedureName)) {
throw new IllegalArgumentException(
"Could not determine name of procedure for @Procedure annotated method: " + method);
}
return new StoredProcedureAttributes(procedureName, createOutputProcedureParameterFrom(method, procedure));
@@ -96,42 +100,57 @@ enum StoredProcedureAttributeSource {
}
/**
* Extract procedure attributes from method and procedure.
*
* @param method
* @param namedStoredProc
* @param procedure
* @return
*/
private StoredProcedureAttributes newProcedureAttributesFrom(Method method,
NamedStoredProcedureQuery namedStoredProc, Procedure procedure) {
private StoredProcedureAttributes newProcedureAttributesFrom(Method method, NamedStoredProcedureQuery namedStoredProc,
Procedure procedure) {
List<ProcedureParameter> outputParameters = new ArrayList<>();
List<ProcedureParameter> outputParameters;
if (!procedure.outputParameterName().isEmpty()) {
// we give the output parameter definition from the @Procedure annotation precedence
outputParameters.add(createOutputProcedureParameterFrom(method, procedure));
outputParameters = Collections.singletonList(createOutputProcedureParameterFrom(method, procedure));
} else {
// try to discover the output parameter
List<StoredProcedureParameter> namedProcedureOutputParameters = extractOutputParametersFrom(namedStoredProc);
for (StoredProcedureParameter outputParameter : namedProcedureOutputParameters) {
outputParameters.add(new ProcedureParameter(
outputParameter.name(), outputParameter.mode(), outputParameter.type()));
}
outputParameters = extractOutputParametersFrom(namedStoredProc).stream() //
.map(namedParameter -> new ProcedureParameter(namedParameter.name(), namedParameter.mode(),
namedParameter.type())) //
.collect(Collectors.toList());
}
return new StoredProcedureAttributes(namedStoredProc.name(), outputParameters, true);
}
/**
* Create a {@link ProcedureParameter} from relevant {@link Method} and {@link Procedure}.
*
* @param method
* @param procedure
* @return
*/
private ProcedureParameter createOutputProcedureParameterFrom(Method method, Procedure procedure) {
return new ProcedureParameter(procedure.outputParameterName(),
procedure.refCursor() ? ParameterMode.REF_CURSOR : ParameterMode.OUT,
method.getReturnType());
procedure.refCursor() ? ParameterMode.REF_CURSOR : ParameterMode.OUT, method.getReturnType());
}
/**
* Translate all the {@Link NamedStoredProcedureQuery} parameters into a {@link List} of
* {@link StoredProcedureParameter}s.
*
* @param namedStoredProc
* @return
*/
private List<StoredProcedureParameter> extractOutputParametersFrom(NamedStoredProcedureQuery namedStoredProc) {
List<StoredProcedureParameter> outputParameters = new ArrayList<StoredProcedureParameter>();
List<StoredProcedureParameter> outputParameters = new ArrayList<>();
for (StoredProcedureParameter param : namedStoredProc.parameters()) {
@@ -190,9 +209,12 @@ enum StoredProcedureAttributeSource {
* @param procedure
* @return
*/
private String derivedNamedProcedureNameFrom(Method method, JpaEntityMetadata<?> entityMetadata, Procedure procedure) {
return StringUtils.hasText(procedure.name()) ? procedure.name() : entityMetadata.getEntityName() + "."
+ method.getName();
private String derivedNamedProcedureNameFrom(Method method, JpaEntityMetadata<?> entityMetadata,
Procedure procedure) {
return StringUtils.hasText(procedure.name()) //
? procedure.name() //
: entityMetadata.getEntityName() + "." + method.getName();
}
/**
@@ -201,7 +223,7 @@ enum StoredProcedureAttributeSource {
*/
private List<NamedStoredProcedureQuery> collectNamedStoredProcedureQueriesFrom(Class<?> entityType) {
List<NamedStoredProcedureQuery> queries = new ArrayList<NamedStoredProcedureQuery>();
List<NamedStoredProcedureQuery> queries = new ArrayList<>();
NamedStoredProcedureQueries namedQueriesAnnotation = AnnotatedElementUtils.findMergedAnnotation(entityType,
NamedStoredProcedureQueries.class);

View File

@@ -15,16 +15,16 @@
*/
package org.springframework.data.jpa.repository.query;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import javax.persistence.StoredProcedureQuery;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.persistence.StoredProcedureQuery;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Stored procedure configuration for JPA 2.1 {@link StoredProcedureQuery}s.
*
@@ -48,7 +48,7 @@ class StoredProcedureAttributes {
/**
* Creates a new {@link StoredProcedureAttributes}.
*
* @param procedureName must not be {@literal null}.
* @param procedureName must not be {@literal null}.
*/
StoredProcedureAttributes(String procedureName, ProcedureParameter parameter) {
this(procedureName, Collections.singletonList(parameter), false);
@@ -57,14 +57,16 @@ class StoredProcedureAttributes {
/**
* Creates a new {@link StoredProcedureAttributes}.
*
* @param procedureName must not be {@literal null}.
* @param procedureName must not be {@literal null}.
* @param namedStoredProcedure flag signaling if the stored procedure has a name.
*/
StoredProcedureAttributes(String procedureName, List<ProcedureParameter> outputProcedureParameters, boolean namedStoredProcedure) {
StoredProcedureAttributes(String procedureName, List<ProcedureParameter> outputProcedureParameters,
boolean namedStoredProcedure) {
Assert.notNull(procedureName, "ProcedureName must not be null!");
Assert.notNull(outputProcedureParameters, "OutputProcedureParameters must not be null!");
Assert.isTrue(outputProcedureParameters.size() != 1 || outputProcedureParameters.get(0) != null, "ProcedureParameters must not have size 1 with a null value");
Assert.isTrue(outputProcedureParameters.size() != 1 || outputProcedureParameters.get(0) != null,
"ProcedureParameters must not have size 1 with a null value");
this.procedureName = procedureName;
this.namedStoredProcedure = namedStoredProcedure;
@@ -77,15 +79,16 @@ class StoredProcedureAttributes {
}
private List<ProcedureParameter> getParametersWithCompletedNames(List<ProcedureParameter> procedureParameters) {
return IntStream.range(0, procedureParameters.size())
.mapToObj(i -> getParameterWithCompletedName(procedureParameters.get(i), i))
return IntStream.range(0, procedureParameters.size()) //
.mapToObj(i -> getParameterWithCompletedName(procedureParameters.get(i), i)) //
.collect(Collectors.toList());
}
private ProcedureParameter getParameterWithCompletedName(ProcedureParameter parameter, int i) {
return new ProcedureParameter(
completeOutputParameterName(i, parameter.getName()),
parameter.getMode(), parameter.getType());
return new ProcedureParameter(completeOutputParameterName(i, parameter.getName()), parameter.getMode(),
parameter.getType());
}
private String completeOutputParameterName(int i, String paramName) {
@@ -130,6 +133,7 @@ class StoredProcedureAttributes {
* @return
*/
public boolean hasReturnValue() {
if (getOutputProcedureParameters().isEmpty())
return false;

View File

@@ -18,20 +18,16 @@ package org.springframework.data.jpa.repository.query;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import javax.persistence.EntityManager;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.ParameterMode;
import javax.persistence.StoredProcedureParameter;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.TypedQuery;
import org.springframework.data.jpa.repository.query.JpaParameters.JpaParameter;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.ResultProcessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -143,7 +139,8 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
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(),
extractOutputParameterValue(outputParameter, i, storedProcedureQuery));
}
return outputValues;
@@ -152,12 +149,13 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
/**
* @return The value of an output parameter either by name or by index.
*/
private Object extractOutputParameterValue(ProcedureParameter outputParameter, Integer index, StoredProcedureQuery storedProcedureQuery) {
private Object extractOutputParameterValue(ProcedureParameter outputParameter, Integer index,
StoredProcedureQuery storedProcedureQuery) {
JpaParameters methodParameters = getQueryMethod().getParameters();
return useNamedParameters && StringUtils.hasText(outputParameter.getName()) ?
storedProcedureQuery.getOutputParameterValue(outputParameter.getName())
return useNamedParameters && StringUtils.hasText(outputParameter.getName())
? storedProcedureQuery.getOutputParameterValue(outputParameter.getName())
: storedProcedureQuery.getOutputParameterValue(methodParameters.getNumberOfParameters() + index + 1);
}
@@ -166,7 +164,8 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
*/
private StoredProcedureQuery createStoredProcedure() {
return procedureAttributes.isNamedStoredProcedure() ? newNamedStoredProcedureQuery()
return procedureAttributes.isNamedStoredProcedure() //
? newNamedStoredProcedureQuery()
: newAdhocStoredProcedureQuery();
}
@@ -205,15 +204,20 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
ProcedureParameter procedureOutput = procedureAttributes.getOutputProcedureParameters().get(0);
/* If the stored procedure returns a ResultSet without using REF_CURSOR,
it is not necessary to declare an output parameter */
if ((isResultSetProcedure() && procedureOutput.getMode() == ParameterMode.REF_CURSOR) || !isResultSetProcedure()) {
/**
* If there is a {@link java.sql.ResultSet} with a {@link ParameterMode#REF_CURSOR}, find the output parameter.
* Otherwise, no need, there is no need to find an output parameter.
*/
if (storedProcedureHasResultSetUsingRefCursor(procedureOutput) || !isResultSetProcedure()) {
if (useNamedParameters) {
procedureQuery.registerStoredProcedureParameter(procedureOutput.getName(), procedureOutput.getType(), procedureOutput.getMode());
procedureQuery.registerStoredProcedureParameter(procedureOutput.getName(), procedureOutput.getType(),
procedureOutput.getMode());
} else {
// Output parameter should be after the input parameters
int outputParameterIndex = params.getNumberOfParameters() + 1;
procedureQuery.registerStoredProcedureParameter(outputParameterIndex, procedureOutput.getType(),
procedureOutput.getMode());
}
@@ -223,18 +227,29 @@ class StoredProcedureJpaQuery extends AbstractJpaQuery {
return procedureQuery;
}
/**
* Does this stored procedure has a {@link java.sql.ResultSet} using {@link ParameterMode#REF_CURSOR}?
*
* @param procedureOutput
* @return
*/
private boolean storedProcedureHasResultSetUsingRefCursor(ProcedureParameter procedureOutput) {
return isResultSetProcedure() && procedureOutput.getMode() == ParameterMode.REF_CURSOR;
}
private StoredProcedureQuery createAdhocStoredProcedureQuery() {
String procedureName = procedureAttributes.getProcedureName();
if (getQueryMethod().isQueryForEntity()) {
return getEntityManager().createStoredProcedureQuery(procedureName,
return getEntityManager().createStoredProcedureQuery(procedureAttributes.getProcedureName(),
getQueryMethod().getEntityInformation().getJavaType());
}
return getEntityManager().createStoredProcedureQuery(procedureName);
return getEntityManager().createStoredProcedureQuery(procedureAttributes.getProcedureName());
}
/**
*
* @return true if the stored procedure will use a ResultSet to return data and not output parameters
*/
private boolean isResultSetProcedure() {

View File

@@ -69,6 +69,8 @@ import com.querydsl.core.types.EntityPath;
* @author Jens Schauder
* @author Stefan Fussenegger
* @author Réda Housni Alaoui
* @author Gabriel Basilio
* @author Greg Turnquist
*/
public class JpaRepositoryFactory extends RepositoryFactorySupport {
@@ -214,6 +216,7 @@ public class JpaRepositoryFactory extends RepositoryFactorySupport {
@Override
protected Optional<QueryLookupStrategy> getQueryLookupStrategy(@Nullable Key key,
QueryMethodEvaluationContextProvider evaluationContextProvider) {
return Optional.of(JpaQueryLookupStrategy.create(entityManager, queryMethodFactory, key, evaluationContextProvider,
escapeCharacter));
}

View File

@@ -28,7 +28,6 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;

View File

@@ -50,6 +50,7 @@ import org.springframework.util.ReflectionUtils;
* @author Jeff Sheets
* @author Jens Schauder
* @author Gabriel Basilio
* @author Greg Turnquist
* @since 1.6
*/
@ExtendWith(MockitoExtension.class)
@@ -72,7 +73,9 @@ class StoredProcedureAttributeSourceUnitTests {
void shouldCreateStoredProcedureAttributesFromProcedureMethodWithImplicitProcedureName() {
StoredProcedureAttributes attr = creator.createFrom(method("plus1inout", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("plus1inout");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -86,6 +89,7 @@ class StoredProcedureAttributeSourceUnitTests {
entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("plus1inout");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -99,6 +103,7 @@ class StoredProcedureAttributeSourceUnitTests {
entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("plus1inout");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -112,6 +117,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("explicitPlus1inoutViaProcedureNameAlias", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("plus1inout");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -125,6 +131,7 @@ class StoredProcedureAttributeSourceUnitTests {
method("explicitPlus1inoutViaProcedureNameAliasAndOutputParameterName", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("plus1inout");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -138,6 +145,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("entityAnnotatedCustomNamedProcedurePlus1IO", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("User.plus1IO");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -151,6 +159,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("entityAnnotatedCustomNamedProcedureOutputParamNamePlus1IO", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("User.plus1IO");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -183,6 +192,7 @@ class StoredProcedureAttributeSourceUnitTests {
StoredProcedureAttributes attr = creator.createFrom(method("plus1", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("User.plus1");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -196,6 +206,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("plus1inoutWithComposedAnnotationOverridingProcedureName", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("plus1inout");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -209,6 +220,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("plus1inoutWithComposedAnnotationOverridingName", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("User.plus1");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Integer.class);
@@ -222,6 +234,7 @@ class StoredProcedureAttributeSourceUnitTests {
entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("0_input_1_row_resultset");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Dummy.class);
@@ -235,6 +248,7 @@ class StoredProcedureAttributeSourceUnitTests {
entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("1_input_1_row_resultset");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(Dummy.class);
@@ -247,6 +261,7 @@ class StoredProcedureAttributeSourceUnitTests {
StoredProcedureAttributes attr = creator.createFrom(method("entityListFromResultSetWithNoInput"), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("0_input_1_resultset");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(List.class);
@@ -261,6 +276,7 @@ class StoredProcedureAttributeSourceUnitTests {
entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("1_input_1_resultset");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(List.class);
@@ -274,6 +290,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("genericObjectListFromResultSetWithInput", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("1_input_1_resultset");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(List.class);
@@ -287,6 +304,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("entityListFromResultSetWithInputAndNamedOutput", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("1_input_1_resultset");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.OUT);
assertThat(outputParameter.getType()).isEqualTo(List.class);
@@ -300,6 +318,7 @@ class StoredProcedureAttributeSourceUnitTests {
.createFrom(method("entityListFromResultSetWithInputAndNamedOutputAndCursor", Integer.class), entityMetadata);
ProcedureParameter outputParameter = attr.getOutputProcedureParameters().get(0);
assertThat(attr.getProcedureName()).isEqualTo("1_input_1_resultset");
assertThat(outputParameter.getMode()).isEqualTo(ParameterMode.REF_CURSOR);
assertThat(outputParameter.getType()).isEqualTo(List.class);
@@ -319,58 +338,50 @@ class StoredProcedureAttributeSourceUnitTests {
/**
* Explicitly mapped to a procedure with name "plus1inout" in database.
*/
@Procedure("plus1inout")
// DATAJPA-455
@Procedure("plus1inout") // DATAJPA-455
Integer explicitlyNamedPlus1inout(Integer arg);
/**
* Explicitly mapped to a procedure with name "plus1inout" in database via alias.
*/
@Procedure(procedureName = "plus1inout")
// DATAJPA-455
@Procedure(procedureName = "plus1inout") // DATAJPA-455
Integer explicitPlus1inoutViaProcedureNameAlias(Integer arg);
/**
* Explicitly mapped to a procedure with name "plus1inout" in database via alias and explicitly named ouput
* Explicitly mapped to a procedure with name "plus1inout" in database via alias and explicitly named output
* parameter.
*/
@Procedure(procedureName = "plus1inout", outputParameterName = "res")
// DATAJPA-1297
@Procedure(procedureName = "plus1inout", outputParameterName = "res") // DATAJPA-1297
Integer explicitPlus1inoutViaProcedureNameAliasAndOutputParameterName(Integer arg);
/**
* Implicitly mapped to a procedure with name "plus1inout" in database via alias.
*/
@Procedure
// DATAJPA-455
@Procedure // DATAJPA-455
Integer plus1inout(Integer arg);
/**
* Explicitly mapped to named stored procedure "User.plus1IO" in {@link EntityManager}.
*/
@Procedure(name = "User.plus1IO")
// DATAJPA-455
@Procedure(name = "User.plus1IO") // DATAJPA-455
Integer entityAnnotatedCustomNamedProcedurePlus1IO(@Param("arg") Integer arg);
/**
* Explicitly mapped to named stored procedure "User.plus1IO" in {@link EntityManager}. With a outputParameterName
* Explicitly mapped to named stored procedure "User.plus1IO" in {@link EntityManager} with an outputParameterName.
*/
@Procedure(name = "User.plus1IO", outputParameterName = "override")
// DATAJPA-707
@Procedure(name = "User.plus1IO", outputParameterName = "override") // DATAJPA-707
Integer entityAnnotatedCustomNamedProcedureOutputParamNamePlus1IO(@Param("arg") Integer arg);
/**
* Explicitly mapped to named stored procedure "User.plus1IO2" in {@link EntityManager}.
*/
@Procedure(name = "User.plus1IO2")
// DATAJPA-707
@Procedure(name = "User.plus1IO2") // DATAJPA-707
Map<String, Integer> entityAnnotatedCustomNamedProcedurePlus1IO2(@Param("arg") Integer arg);
/**
* Implicitly mapped to named stored procedure "User.plus1" in {@link EntityManager}.
*/
@Procedure
// DATAJPA-455
@Procedure // DATAJPA-455
Integer plus1(@Param("arg") Integer arg);
@ComposedProcedureUsingAliasFor(explicitProcedureName = "plus1inout")
@@ -379,32 +390,25 @@ class StoredProcedureAttributeSourceUnitTests {
@ComposedProcedureUsingAliasFor(emProcedureName = "User.plus1")
Integer plus1inoutWithComposedAnnotationOverridingName(Integer arg);
@Procedure("0_input_1_row_resultset")
// DATAJPA-1657
@Procedure("0_input_1_row_resultset") // DATAJPA-1657
Dummy singleEntityFrom1RowResultSetAndNoInput();
@Procedure("1_input_1_row_resultset")
// DATAJPA-1657
@Procedure("1_input_1_row_resultset") // DATAJPA-1657
Dummy singleEntityFrom1RowResultSetWithInput(Integer arg);
@Procedure("0_input_1_resultset")
// DATAJPA-1657
@Procedure("0_input_1_resultset") // DATAJPA-1657
List<Dummy> entityListFromResultSetWithNoInput();
@Procedure("1_input_1_resultset")
// DATAJPA-1657
@Procedure("1_input_1_resultset") // DATAJPA-1657
List<Dummy> entityListFromResultSetWithInput(Integer arg);
@Procedure("1_input_1_resultset")
// DATAJPA-1657
@Procedure("1_input_1_resultset") // DATAJPA-1657
List<Object[]> genericObjectListFromResultSetWithInput(Integer arg);
@Procedure(value = "1_input_1_resultset", outputParameterName = "dummies")
// DATAJPA-1657
@Procedure(value = "1_input_1_resultset", outputParameterName = "dummies") // DATAJPA-1657
List<Dummy> entityListFromResultSetWithInputAndNamedOutput(Integer arg);
@Procedure(value = "1_input_1_resultset", outputParameterName = "dummies", refCursor = true)
// DATAJPA-1657
@Procedure(value = "1_input_1_resultset", outputParameterName = "dummies", refCursor = true) // DATAJPA-1657
List<Dummy> entityListFromResultSetWithInputAndNamedOutputAndCursor(Integer arg);
}

View File

@@ -18,10 +18,10 @@ package org.springframework.data.jpa.repository.query;
import static org.assertj.core.api.Assertions.*;
import static org.springframework.data.jpa.repository.query.StoredProcedureAttributes.*;
import org.junit.jupiter.api.Test;
import javax.persistence.ParameterMode;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@link StoredProcedureAttributes}.
*
@@ -33,8 +33,8 @@ class StoredProcedureAttributesUnitTests {
@Test // DATAJPA-681
void usesSyntheticOutputParameterNameForAdhocProcedureWithoutOutputName() {
ProcedureParameter outputParameter = new ProcedureParameter(null, ParameterMode.OUT, Long.class);
StoredProcedureAttributes attributes = new StoredProcedureAttributes("procedure", outputParameter);
StoredProcedureAttributes attributes = new StoredProcedureAttributes("procedure",
new ProcedureParameter(null, ParameterMode.OUT, Long.class));
assertThat(attributes.getOutputProcedureParameters().get(0).getName()).isEqualTo(SYNTHETIC_OUTPUT_PARAMETER_NAME);
}
}