[英]Spring Boot Data JPA receive Multiple Out Parameters from stored procedure
I'm trying to call stored procedure with multiple out parameters via Spring Boot Data JPA (v2.2.6), but receive an error:我正在尝试通过 Spring 引导数据 JPA (v2.2.6) 调用具有多个输出参数的存储过程,但收到错误:
DEBUG [http-nio-8080-exec-1] org.hibernate.engine.jdbc.spi.SqlStatementLogger: {call TEST_SP(?,?,?)}
RACE [http-nio-8080-exec-1] org.hibernate.type.descriptor.sql.BasicBinder: binding parameter [DOC_NAME] as [VARCHAR] - [ololo]
ERROR [http-nio-8080-exec-1] org.apache.juli.logging.DirectJDKLog: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: OUT/INOUT parameter not available: DOC_ID; nested exception is java.lang.IllegalArgumentException: OUT/INOUT parameter not available: DOC_ID] with root cause
java.lang.IllegalArgumentException: OUT/INOUT parameter not available: DOC_ID
Stored procedure in MS SQL Server 2012: MS SQL Server 2012 中的存储过程:
CREATE PROCEDURE [dbo].[TEST_SP]
@DOC_ID bigint output,
@DOC_GUID nvarchar(255) output,
@DOC_NAME nvarchar(255)
AS
BEGIN
SET NOCOUNT ON;
SELECT @DOC_ID = 6666, @DOC_GUID = @DOC_NAME
END
Here my entity (it is not related to SP):这是我的实体(它与 SP 无关):
@Data
@Entity
@NamedStoredProcedureQuery(name = "SomeEntity.test", procedureName = "TEST_SP", parameters = {
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "DOC_ID", type = Long.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "DOC_GUID", type = String.class),
@StoredProcedureParameter(mode = ParameterMode.IN, name = "DOC_NAME", type = String.class)
})
@Table(name = "DOCUMENT_DATA")
public class SomeEntity {
// some variables
}
Here my repository:这是我的存储库:
public interface SomeRepository extends JpaRepository<SomeEntity, Long> {
@Procedure(name = "SomeEntity.test")
Map<String, Object> testSp(@Param("DOC_NAME") String docName);
}
Here how I call it:这里我怎么称呼它:
@RestController
public class Controller {
@Autowired
SomeRepository repository;
@GetMapping("test")
String test() {
return repository.testSp("ololo").toString();
}
}
As example I used these links: https://github.com/spring-projects/spring-data-jpa/blob/master/src/test/java/org/springframework/data/jpa/domain/sample/User.java#L77 https://github.com/spring-projects/spring-data-jpa/blob/e27933455efa6d1821dea23abd2bbe109b5d59a7/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java#L362例如,我使用了这些链接: https://github.com/spring-projects/spring-data-jpa/blob/master/src/test/java/org/springframework/data/jpa/domain/sample/User.java #L77 https://github.com/spring-projects/spring-data-jpa/blob/e27933455efa6d1821dea23abd2bbe109b5d59a7/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java#L36
Upd: I've tried with Oracle 11g更新:我试过 Oracle 11g
CREATE OR REPLACE PROCEDURE test_sp(x OUT INTEGER, y OUT INTEGER) AS
BEGIN
x := 17; y := 93;
END;
@NamedStoredProcedureQuery(name = "EstatementsDataEntity.test", procedureName = "test_sp", parameters = {
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "x", type = Integer.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "y", type = Integer.class)
})
But receive almost identical error:但收到几乎相同的错误:
java.lang.IllegalArgumentException: OUT/INOUT parameter not available: 1
I could not find working solution with annotations and submitted a bug DATAJPA-1722我找不到带有注释的工作解决方案并提交了错误DATAJPA-1722
But I could managed to solve issue using EntityManager
:但我可以设法使用
EntityManager
解决问题:
@SpringBootTest
class DemoApplicationTests {
@PersistenceContext
private EntityManager em;
@Test
void callStoredProcedureUsingEntitiManager() {
StoredProcedureQuery proc = em.createStoredProcedureQuery("test_sp");
proc.registerStoredProcedureParameter("x", Integer.class, ParameterMode.OUT);
proc.registerStoredProcedureParameter("y", Integer.class, ParameterMode.OUT);
proc.execute();
assertThat(proc.getOutputParameterValue("x")).isEqualTo(17);
assertThat(proc.getOutputParameterValue("y")).isEqualTo(93);
}
}
FYI for anyone still using older versions of Spring Boot.仅供仍在使用旧版本 Spring 引导的任何人使用。 This error was caused by calling a procedure without enclosing it in a transaction.
此错误是由调用过程而不将其包含在事务中引起的。 Error message was a bit of a red herring but the fix was to add @Transaction to the caller.
错误消息有点像红鲱鱼,但解决方法是将@Transaction 添加到调用者。
In the example above I'd include a service layer class between Controller and SomeRepository and annotate my service layer method as transactional.在上面的示例中,我将在 Controller 和 SomeRepository 之间包含一个服务层 class 并将我的服务层方法注释为事务性的。
ie IE
@Service
public class SomeService{
@Autowired
SomeRepository someRepo;
@Transactional
public Map<String, Object> testSp(String docName){
return someRepo.testSp(docName);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.