将SpringBoot与MSSQL服务器存储过程一起使用时,当值为null时,存储过程无法执行。调用时,该值的默认值为null。 如果排除了参数,则proc工作。但由于这些是可选参数,我可以选择调用存储过程吗?
当我尝试在调用存储过程时传递null时,它会因此错误而失败。
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: Error calling CallableStatement.getMoreResults; SQL [saveInfo]; nested exception is org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults] with root cause
java.sql.SQLException: Parameter #1 has not been set.
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1049)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:563)
at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.execute(JtdsPreparedStatement.java:787)
at org.hibernate.result.internal.OutputsImpl.<init>(OutputsImpl.java:52)
at org.hibernate.procedure.internal.ProcedureOutputsImpl.<init>(ProcedureOutputsImpl.java:32)
at org.hibernate.procedure.internal.ProcedureCallImpl.buildOutputs(ProcedureCallImpl.java:411)
at org.hibernate.procedure.internal.ProcedureCallImpl.getOutputs(ProcedureCallImpl.java:363)
at org.hibernate.jpa.internal.StoredProcedureQueryImpl.outputs(StoredProcedureQueryImpl.java:234)
at org.hibernate.jpa.internal.StoredProcedureQueryImpl.execute(StoredProcedureQueryImpl.java:217)
at com.tda.etfmc.service.repository.ETFMgmtRepository.saveCommissionFreeETF(ETFMgmtRepository.java:87)
at com.tda.etfmc.service.repository.ETFMgmtRepository$$FastClassBySpringCGLIB$$d1d68142.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:721)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:656)
StoredProc:
CREATE PROCEDURE [dbo].[saveInfo]
@input1 varchar(16) = NULL,
@input2 varchar(16) = NULL
AS
BEGIN
//do save here
END
GO
@Repository
public class MyRepository {
private EntityManager entityManager;
public MyRepository(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Procedure(name = "saveInfo")
@Transactional
public void saveInfo(List<Input> inputList) throws SQLException {
StoredProcedureQuery saveInfo;
for (Input input : inputList) {
saveInfo = entityManager.createNamedStoredProcedureQuery("saveInfo");
saveInfo.setParameter("input1", input.getInput1());// pass null here
saveInfo.setParameter("input2", input.getInput2());
saveInfo.execute();
}
}
}
@Data
@NamedStoredProcedureQuery(name = "saveInfo", procedureName = "saveInfo", parameters = {
@StoredProcedureParameter(name = "input1", type = String.class, mode = ParameterMode.IN),
@StoredProcedureParameter(name = "input2", type = String.class, mode = ParameterMode.IN) })
class Input implements Serializable {
private static final long serialVersionUID = 1L;
@Column(name = "@input1")
private String input1;
@Column(name = "@input2")
private String input2;
}