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());
我正在使用 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());