【问题标题】:Store Stored Procedure return value using JPA使用 JPA 存储存储过程返回值
【发布时间】:2018-10-19 03:42:59
【问题描述】:

我正在尝试使用 JPA(和 Spring Boot 2)来执行 SQL Server 存储过程。流程如下:

CREATE Procedure [dbo].[GetStatus] 
@statusId   char(32),
@bar    int
AS
BEGIN TRY
    SELECT IIF(COUNT(1)>0 , 1, 0)   FROM Status WITH (NOLOCK) 
    WHERE statusId = @statusId AND bar = @bar
END TRY
BEGIN CATCH
    EXEC EventLog @@PROCID
END CATCH
GO

我正在尝试捕获返回值,但找不到这样做的方法。我的实体是:

@Entity
@Table(name = "status")
@NamedStoredProcedureQueries({
        @NamedStoredProcedureQuery(name = "getStatusByStatusId",
                procedureName = "GetStatus",
                parameters = {
                        @StoredProcedureParameter(mode = ParameterMode.IN, name = "statusId", type = String.class),
                        @StoredProcedureParameter(mode = ParameterMode.IN, name = "bar", type = Integer.class)                    })
})
public class Status implements Serializable {
    @Id
    @GeneratedValue
    private Long id;
    private Integer bar;
    private String statusId;
    private Date createDate;
}

我的存储库是:

@Repository
public interface StatusRepository extends JpaRepository<Status, Long> {
    @Procedure("GetStatus")
    int getStatusByStatusId(@Param("statusId") String statusId, @Param("bar") Integer bar);
}

当我从服务层运行这个方法时,我得到一个错误:

"没有为存储过程定义参数输出..."

我尝试添加参数(通过将其命名为计数和类型为整数)。我尝试了 List, Object[] 但没有任何效果。 唯一有效的是,如果我将存储库方法更改为返回 void。但在那种情况下,我无法获得返回值。 所以,我的问题是如何获得 SELECT 值?任何帮助表示赞赏。我的 app.yml 有:

  datasource:
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    url: jdbc:sqlserver://dev.lsd.com:1433;databaseName=Qrex;integratedSecurity=true;MultiSubnetFailover=true;authenticationScheme=JavaKerberos
    username:
    password:
  jpa:
    hibernate:
      ddl-auto: none
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
    show-sql: true
    database-platform: org.hibernate.dialect.SQLServerDialect
    database: sql_server

我的 gradle 依赖是:

compile "com.microsoft.sqlserver:mssql-jdbc:6.4.0.jre8"

【问题讨论】:

    标签: sql-server spring-boot stored-procedures spring-data-jpa


    【解决方案1】:

    我不相信 JPA 可以处理返回任意数量的结果集和/或更新计数和/或错误消息的存储过程。我见过的所有例子都相当简单。您的过程返回:

    • 包含投影的结果集(不是实体!)
    • 无论EventLog 过程返回什么。可以是任何东西

    这里直接用JDBC怎么做(没有OUT参数,所以普通的PreparedStatement就可以了。

    以下是使用 JDBC 仅获取一个结果集的方法:

    try (PreparedStatement stmt = connection.prepareStatement(
        "EXEC [GetStatus] ?, ?"
    )) {
        stmt.setString(1, statusId);
        stmt.setInt(2, bar);
    
        if (stmt.execute()) {
            try (ResultSet rs = stmt.getResultSet()) {
                // Do your thing
            }
        }
    }
    

    这是获取任意数量的结果集的方法

    如果您还想检索 EventLog 生成的任何内容,您可能更喜欢调用它:

    try (PreparedStatement stmt = connection.prepareStatement(
        "EXEC [GetStatus] ?, ?"
    )) {
        stmt.setString(1, statusId);
        stmt.setInt(2, bar);
    
        fetchLoop:
        for (int i = 0, updateCount = 0; i < 256; i++) {
            boolean result = (i == 0)
                ? s.execute()
                : s.getMoreResults();
    
            if (result)
                try (ResultSet rs = s.getResultSet()) {
                    System.out.println("Result      :");
    
                    while (rs.next())
                        System.out.println("  " + rs.getString(1));
                }
            else if ((updateCount = s.getUpdateCount()) != -1)
                System.out.println("Update Count: " + updateCount);
            else
                break fetchLoop;
        }
    }
    

    I've described this approach of fetching arbitrary result sets and update counts more in detail here,特别是如何正确获取异常和警告。

    如果您使用这种方法,您可能希望将该逻辑包装在一些库代码中。

    使用 jOOQ

    也可以使用jOOQ 处理这些事情(免责声明:我为供应商工作),如果您可以致电:

    Results results = ctx.fetchMany("EXEC [GetStatus] ?, ?", statusId, bar);
    

    获取org.jooq.Results 类型,该类型包含交错的结果集、更新计数、异常和警告

    【讨论】:

      猜你喜欢
      • 2010-11-23
      • 1970-01-01
      • 2010-11-02
      • 2015-11-06
      • 2021-06-13
      • 2017-07-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多