Spring Data - 从 Blob 读取字节时关闭的可调用语句

Spring Data - Callable statement being closed while reading bytes from a Blob

提问人:James 提问时间:9/30/2023 最后编辑:James 更新时间:9/30/2023 访问量:37

问:

背景

我有一个 Spring Boot 3.0 应用程序,它使用 Spring Data JPA 来调用存储过程。下面是调用存储过程的 Spring Data 存储库:

public interface CarRepository extends Repository<Car, Long> {
    
    @Procedure(value="pValuation", outputParameterName="reportData")
    Blob getReportData(String carTypes, LocalDate tradeDate);

存储过程位于 SQL Server 2016 数据库中:

CREATE PROCEDURE [dbo].[pValuation]
    @carTypes nvarchar(max),
    @tradeDate datetime,
    @reportData varbinary(max) out
AS
BEGIN
    EXEC RDO.pValuation
        @reportData = @reportData out,
        @CarTypes = @carTypes ,
        @Date = @tradeDate,
        @IncludeBaseData = true
END

我使用 a 而不是 a 作为 out 参数,因为Blobbyte[]varbinary(max)

  1. MS SQL JDBC 驱动程序(版本 mssql-jdbc-11.2.3.jre17)在使用时返回最大 8000 字节,并且byte[]
  2. 我的存储过程返回 > 8000 字节

我需要将其转换为字节数组以进行其他处理:Blob

@Service
@RequiredArgsConstructor
@Slf4j
public class CarService {

    private final CarRepository carRepository;

    public Set<CarDto> getValuations(LocalDate date) {
        
        Blob reportData = carRepository.getReportData("sedan,truck", date);
        log.debug("got Blob");
        try {
            byte[] b= reportData.getBytes(1, (int) reportData.length());
            log.debug("exception thrown from line above... will never log this");
            return carRepository.getCarValuations(b);
        } 
        catch (SQLException convertBlobToBytesException) {
            log.error(convertBlobToBytesException.toString());
        }
    }

问题

转换为 via the line 时:Blobbyte[]

reportData.getBytes(1, (int) reportData.length())

抛出 A。打开MSSQL JDBC跟踪日志记录后,我发现该语句在获取后立即关闭(即在执行此操作后立即关闭:)。日志如下:SQLExcpetionBlobBlob reportData = carRepository.getReportData("sedan,truck", date);

2023-09-29T17:33:05.762-05:00 调试 29104 --- [http-nio-8080-exec-1] c.m.s.jdbc.internals.SQLServerException : *** SQLException:SQLServerCallableStatement:119 com.microsoft.sqlserver.jdbc.SQLServerException:语句为 闭。该语句已关闭。

2023-09-29T17:33:05.771-05:00 错误 29104 --- [http-nio-8080-exec-1] com.example.service.CarService:得到 Blob

然后,日志来自报告关闭输入流、关闭输出流,然后关闭 TCP 套接字。由于调用 尝试从此闭合流中读取字节,因此会出现如下错误:TDS.ChannelreportData.getBytes

2023-09-29T17:33:05.773-05:00 错误 29104 --- [http-nio-8080-exec-1] com.example.service.CarService: com.microsoft.sqlserver.jdbc.SQLServerException:TDS 协议 流无效。

问题

如何使用 Spring Data JPA 从 Blob 中获取字节?

我试过什么

我尝试将方法包装在事务中,但这会导致应用程序在从存储过程调用中读取数据包时挂起。getValuations

我可以在不使用 Spring Data JPA 的情况下获取字节,如下所示:

@Service
@RequiredArgsConstructor
@Slf4j
public class CarService {
  
    private final CarRepository carRepository;
    private final EntityManager em;

    public Set<CarDto> getValuations(LocalDate date) {
        
        StoredProcedureQuery q = em.createStoredProcedureQuery("pValuation");
        q.registerStoredProcedureParameter("carTypes", String.class, ParameterMode.IN);
        q.registerStoredProcedureParameter("tradeDate", LocalDate.class, ParameterMode.IN);
        q.registerStoredProcedureParameter("reportData", Blob.class, ParameterMode.OUT);
        q.setParameter("carTypes", "sedan,truck");
        q.setParameter("tradeDate", date);
        q.execute();
        
        Blob reportData = (Blob) q.getOutputParameterValue("reportData");
        
        log.debug("got Blob");
        try {
            byte[] b= reportData.getBytes(1, (int) reportData.length());
            log.debug("got bytes");
            return carRepository.getCarValuations(b);
        } 
        catch (SQLException convertBlobToBytesException) {
                log.error(convertBlobToBytesException.toString());
        }
    }

这段代码有效,但我想知道如何使用 Spring Data JPA 做到这一点。

spring-data-jpa spring-transactions mssql-jdbc

评论


答: 暂无答案