我试图使用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);
}
当我从服务层运行此方法时,出现错误:
&#34;未为存储过程定义参数输出...&#34;
我尝试添加参数(通过命名计数并键入为Integer)。我尝试了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"
答案 0 :(得分:0)
我不相信JPA可以处理返回任意数量的结果集和/或更新计数和/或错误消息的存储过程。我见过的所有例子都相当简单。您的程序返回:
EventLog
程序返回什么。可能是任何事情以下是如何直接使用JDBC(没有OUT
个参数,所以普通的PreparedStatement
会这样做。
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来做这些事情(免责声明:我为供应商工作),如果你可以致电:
Results results = ctx.fetchMany("EXEC [GetStatus] ?, ?", statusId, bar);
获取org.jooq.Results
类型,包含交错结果集,更新计数,例外和警告