【问题标题】:JDBC - varbinary(max) out parameter of stored procedure is truncated to 8000 bytesJDBC - 存储过程的 varbinary(max) out 参数被截断为 8000 字节
【发布时间】:2016-10-06 18:50:35
【问题描述】:

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

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

这是存储过程的签名:

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

我的实体类是:

@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 个字节。当我在 SQL Server Management Studio 中运行相同的存储过程时,我注意到它有大约 10,000 个字节并以十六进制代码 FFFF 结束。

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

如何防止这种截断?我应该为 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

【问题讨论】:

  • 8000 字节听起来很熟悉。我建议像风一样使用谷歌搜索。
  • 我试过了。似乎找不到任何确定的东西
  • 经过相当多的研究,它似乎是一个超过 2 年的错误。我希望我错了,它已经解决了。这是致命的问题。我不能使用 Microsoft SQL Server 驱动程序 b/c 它有自己的致命问题,即必须使用非空值声明默认参数。
  • 我在sourceforge.net/p/jtds/bugs/766提交了一个错误报告
  • 它发现 Microsoft 的 SQL Server JDBC 驱动程序表现出相同的行为(即它在 8000 字节处截断)。 SQL Server 过去对varbinary 最多有 8000 个字节。我想这些 SQL Server JDBC 驱动程序从未更新以考虑增加的大小。

标签: sql-server jpa jdbc spring-data-jpa jtds


【解决方案1】:

使用微软的 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 Server,则必须转换回字节数组,如下所示:

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

【讨论】:

    猜你喜欢
    • 2011-06-02
    • 2015-03-07
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-21
    相关资源
    最近更新 更多