JDBC - 存储过程的 varbinary(max) out 参数被截断为 8000 字节

JDBC - varbinary(max) out parameter of stored procedure is truncated to 8000 bytes

我正在使用 Spring Data JPA 1.10.2 和 jTds 1.3.1 来调用存储过程。

存储过程有一个 out 参数,@data 类型为 varbinary(max)。 @data 包含大约 ~10,000 个字节。

这是存储过程签名:

ALTER procedure [User].[pTest]
      @data varbinary(max) out
      ,@name nvarchar(max) = null
      ,@date datetime
as
begin
.
.
.

我的实体 class 是:

@Entity
@NamedStoredProcedureQuery(name = "User.getUser", procedureName = "User.pTest", parameters = {
        @StoredProcedureParameter(mode = ParameterMode.OUT, name = "data", type = byte[].class),  
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "name", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "date", type = Date.class)
          })
@Data //lombok
public class User {


    // serves no purpose other than to meet
    // JPA requirement
    @Id
    private Long id;
}

存储库代码是

public interface UserRepository  extends Repository<User, Long> {

    @Procedure("User.pTest")
    byte[] getUserSession(@Param("name") String name, 
            @Param("date") Date date
            );

}

我的测试代码如下,当我 运行 它时,我得到错误:

@Test
public void testGettingApxSession() {
    Calendar cal = new GregorianCalendar(2016,6,5);
    byte[] b = userRepository.getUserSession("myName", cal.getTime());
}

当我使用 @data 注销时:

    StringBuilder sb = new StringBuilder();
    for (byte a : b) {
        sb.append(String.format("%02X ", a));
    }

我注意到只返回了 8,000 个字节。当我在 运行 Server Management Studio 中 运行 相同的存储过程时,我注意到它有大约 10,000 个字节并且以十六进制代码 FFFF 结束。

因此,当 运行 从我的 Java 应用程序中调用存储过程时,我的结果似乎被 t运行 了。

我怎样才能防止这种情况发生运行?我应该为 varbinary(max) 而不是 byte[] 指定不同的数据类型吗?

更新

我也尝试过 Microsoft 的 JDBC 驱动程序 (v 6.0.7728.100) 并遇到了同样的问题。我的猜测是 JDBC 驱动程序(我认为)基于最大数量 n 将最大值设为 8000,您可以在 varbinary(n) 中指定。但是,varbinary 的最大容量远大于 8000,由 varbinary(max) 指定。 varbinary(max) 可以容纳 2^31 - 1 个字节。查看我的问题和其他人的回答 here

使用微软的JDBC驱动,指定输出参数类型为Blob:

@Entity
@NamedStoredProcedureQuery(name = "User.getUser", procedureName = "User.pTest", parameters = {
        @StoredProcedureParameter(mode = ParameterMode.OUT, name = "data", type = Blob.class),  
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "name", type = String.class),
        @StoredProcedureParameter(mode = ParameterMode.IN, name = "date", type = Date.class)
          })

注意:这不适用于 jTDS。它仍然会截断大于 8000 字节的任何内容。

如果Blob需要传回SQL服务器,必须按如下方式转回字节数组:

byte[] bytes = blob.getBytes(1, (int) blob.length());