简体   繁体   English

JPA - 可以在不提供可选参数的情况下调用存储过程吗?

[英]JPA - Can a stored procedure be called without providing optional parameters?

I'm calling a third party stored procedure with a lot of optional parameters. 我正在使用许多可选参数调用第三方存储过程。 It's in MS SQL Server 2008 R2 and looks like this: 它位于MS SQL Server 2008 R2中,如下所示:

procedure [dbo].[pTest]
    @ReportDate varbinary(max) out, 
    @Optional1 varchar(max) = null,
    @Optional2 varbinary(max) = null,
    @Date varchar(max) = null,
    -- ~20 more optional params of various types 
as
begin
select * from test
end

I'm calling it from java using Spring Data JPA 1.10.2 with com.microsoft.sqlserver's sqljdbc 4.2. 我使用Spring Data JPA 1.10.2和com.microsoft.sqlserver的sqljdbc 4.2从java中调用它。

I only ever want to call the procedure with two params ReportDate and Date. 我只想用两个参数ReportDate和Date来调用该过程。 The rest of the params can stay at the default value (ie null). 其余的参数可以保持默认值(即null)。 My code is as follows: 我的代码如下:

@Entity
@NamedStoredProcedureQuery(name = "Test.get", procedureName = "pTest", parameters = {
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "ReportData", type = byte[].class),          
@StoredProcedureParameter(mode = ParameterMode.IN, name = "Date", type = String.class)

          })
public class Test {

    // serves no purpose other than to meet
    // JPA requirement
    @Id
    private byte[] reportData;
}

Spring data repository: Spring数据存储库:

public interface TestRepository  extends Repository<Test, Long> {
    @Procedure("pTest")
    byte[] get(@Param("Date") String date);
}

Test code: 测试代码:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional(transactionManager="transactionManager")
public class TestRepositoryTest {

    @Autowired
    private TestRepository testRepository;

    @Test
    public void testGet() throws SQLException {

        byte[] blob = testRepository.get("hi");
        //error occurs
    }

}

I get the following error though: 我收到以下错误:

   o.h.engine.jdbc.spi.SqlExceptionHelper   : Error preparing CallableStatement [pTest]

com.microsoft.sqlserver.jdbc.SQLServerException: The index 4 is out of range.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:191) ~[sqljdbc-4.2.jar:na]

I'm getting this because I did not specify Optional1 and Optional2. 我得到这个是因为我没有指定Optional1和Optional2。 Now, if I add the Optional1 and Optional2 as @StoredProcedureParameter s and as paramters to getTest method of the TestRepository , I no longer get the error. 现在,如果我将Optional1和Optional2添加为@StoredProcedureParameter并作为TestRepository getTest方法的参数,我不再收到错误。 But then, I have to pass in a non-null values or otherwise I get another error complaining that I passed no value. 但是,我必须传入一个非空值,否则我会得到另一个错误,抱怨我没有传递任何值。

How can I call this stored procedure preferably without specifying Optional1 and Optional2? 如何在不指定Optional1和Optional2的情况下优先调用此存储过程?

In some cases, I need to call a stored procedure where the 15th parameter is all I need to set. 在某些情况下,我需要调用一个存储过程,其中第15个参数是我需要设置的。 I really prefer not having to define the other 14 parameters in my code. 我真的不想在我的代码中定义其他14个参数。 Even if I did that, I cannot set them to null. 即使我这样做,我也不能将它们设置为null。

It's not possible using Microsoft's JDBC driver. 使用Microsoft的JDBC驱动程序是不可能的。 Two options: 两种选择:

  1. Use jTDS (which is not an option if the stored procedure returns >8000 bytes) 使用jTDS(如果存储过程返回> 8000字节,则不能选择)
  2. Create a wrapper stored procedure that only has the params that are needed and have it call the other stored procedure. 创建一个包装器存储过程,该过程只包含所需的参数并让它调用另一个存储过程。 This may not be an option if you don't have permissions to create stored procedures on the database. 如果您没有权限在数据库上创建存储过程,则可能无法选择此选项。

In my case, option 2 works because I do have permission to create stored procedures. 在我的情况下,选项2有效,因为我有权创建存储过程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM