[英]Spring Boot invalidDataAccessApiUsageException - OUT/INOUT Parameter is not available
i'm using an Oracle stored procedure in Spring Boot which has some IN/OUT parameters.我在 Spring Boot 中使用了一个 Oracle 存储过程,它有一些 IN/OUT 参数。
When i'm getting an out parameter it throws an exception invalidDataAccessApiUsageException: OUT/INOUT Parameter is not available: ent_mensaje.
当我得到一个 out 参数时,它会抛出一个异常
invalidDataAccessApiUsageException: OUT/INOUT Parameter is not available: ent_mensaje.
This is the stored procedure definition这是存储过程定义
create or replace PROCEDURE fon_anula_programacion (
ent_numero_operacion IN NUMBER,
ent_numero_fisico IN VARCHAR2,
ent_mensaje IN OUT VARCHAR2,
ent_canal_origen IN OUT VARCHAR2,
ent_senal_proceso IN OUT VARCHAR2,
ent_senal_commit IN OUT VARCHAR2,
ent_sw_pos IN OUT NUMBER
) IS
...
Entity class whit its @NamedStoredProcedureQuery实体 class 及其@NamedStoredProcedureQuery
@Getter
@Setter
@Entity
@NoArgsConstructor
@NamedStoredProcedureQueries({
@NamedStoredProcedureQuery(name = "Valores.AnularAdicionFondoSif",
procedureName = "FON.FON_ANULA_PROGRAMACION",
resultClasses = DTOAnularAdicionSIF.class,
parameters = {
@StoredProcedureParameter(name = "ent_numero_operacion", type = BigDecimal.class, mode = ParameterMode.IN),
@StoredProcedureParameter(name = "ent_numero_fisico", type = String.class, mode = ParameterMode.IN),
@StoredProcedureParameter(name = "ent_mensaje", type = String.class, mode = ParameterMode.INOUT),
@StoredProcedureParameter(name = "ent_canal_origen", type = String.class, mode = ParameterMode.INOUT),
@StoredProcedureParameter(name = "ent_senal_proceso", type = String.class, mode = ParameterMode.INOUT),
@StoredProcedureParameter(name = "ent_senal_commit", type = String.class, mode = ParameterMode.INOUT),
@StoredProcedureParameter(name = "ent_sw_pos", type = BigDecimal.class, mode = ParameterMode.INOUT)
}
)
})
public class DTOAnularAdicionSIF {
@Id
@Column
private BigDecimal Numero_operacion;
@Column
private String Numero_fisico;
@Column
private String Mensaje;
@Column
private String Canal_origen;
@Column
private String Senal_proceso;
@Column
private String Senal_commit;
@Column
private BigDecimal Sw_pos;
}
My Params class我的参数 class
public class AnularAdicionSIFParameters {
@Params(name = "ent_numero_operacion",direction = Params.Direction.IN)
private BigDecimal Numero_operacion;
@Params(name = "ent_numero_fisico",direction = Params.Direction.IN)
private String Numero_fisico;
@Params(name = "ent_mensaje",direction = Params.Direction.INOUT)
private String Mensaje;
@Params(name = "ent_canal_origen",direction = Params.Direction.INOUT)
private String Canal_origen;
@Params(name = "ent_senal_proceso",direction = Params.Direction.INOUT)
private String Senal_proceso;
@Params(name = "ent_senal_commit",direction = Params.Direction.INOUT)
private String Senal_commit;
@Params(name = "ent_sw_pos",direction = Params.Direction.INOUT)
private BigDecimal Sw_pos;
}
Sending parameters发送参数
AnularAdicionSIFParameters anularAdicionSIFParameters = AnularAdicionSIFParameters.builder()
.Numero_operacion(BigDecimal.valueOf(Double.parseDouble(comprobante)))
.Numero_fisico(numerofisico)
.Senal_commit("S")
.Canal_origen(canal)
.Senal_proceso("S")
.Mensaje("")
.Sw_pos(BigDecimal.valueOf(0))
.build();
String response = repository.AnularAdicionReturnMensaje(anularAdicionSIFParameters);
Repository method存储库方法
public String AnularAdicionReturnMensaje(AnularAdicionSIFParameters parameters) throws IllegalAccessException{
String name_procedure = "Valores.AnularAdicionFondoSif";
//super is the class who set the parameters and execute the procedure
ResponseProcedure<AnularAdicionSIF> respuestaSif = super.runNamedStoredProcedure(name_procedure,parameters);
return respuestaSif.getOutput().get("ent_mensaje").toString();
}
Setting the parameters and executing the procedure设置参数并执行程序
public ResponseProcedure<E> runNamedStoredProcedure(String nameProcedure, Object params) throws IllegalAccessException {
StoredProcedureQuery storedProcedureQuery = em.createNamedStoredProcedureQuery(nameProcedure);
Map<String, Object> output = new HashMap<>();
Class<?> objectClass = params.getClass();
Field[] extend = objectClass.getSuperclass().getDeclaredFields();
Field[] base = objectClass.getDeclaredFields();
Field[] allFields = new Field[extend.length + base.length];
Arrays.setAll(allFields, i ->
(i < extend.length ? extend[i] : base[i - extend.length]));
for (Field field: allFields) {
field.setAccessible(true);
if (field.isAnnotationPresent(Params.class)) {
Params param = field.getAnnotation(Params.class);
if(param.direction() == Params.Direction.IN || param.direction() == Params.Direction.INOUT)
storedProcedureQuery.setParameter(param.name(), (field.get(params) != null ) ? field.get(params) : "");
}
}
storedProcedureQuery.execute();
Arrays.stream(allFields).filter(field -> (field.getAnnotation(Params.class).direction() == Params.Direction.OUT || field.getAnnotation(Params.class).direction() == Params.Direction.INOUT))
.forEach(ff ->{
Params param = ff.getAnnotation(Params.class);
output.put(param.name(), storedProcedureQuery.getOutputParameterValue(param.name()));
});
return new ResponseProcedure<E>(toList(storedProcedureQuery.getResultList()), output);
}
And the error: OUT/INOUT parameter not available: ent_mensaje; nested exception is java.lang.IllegalArgumentException: OUT/INOUT parameter not available: ent_mensaje
并且错误:
OUT/INOUT parameter not available: ent_mensaje; nested exception is java.lang.IllegalArgumentException: OUT/INOUT parameter not available: ent_mensaje
OUT/INOUT parameter not available: ent_mensaje; nested exception is java.lang.IllegalArgumentException: OUT/INOUT parameter not available: ent_mensaje
I fixed by adding @Transactional to the method that performs the call to repository.我通过将@Transactional 添加到执行对存储库的调用的方法来修复。 like @Parawata comments in this answer
喜欢这个答案中的@Parawata评论
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.