【问题标题】:SQL server procedure call with Spring boot jpa error: "Unable to extract OUT/INOUT parameter value"带有 Spring boot jpa 错误的 SQL 服务器过程调用:“无法提取 OUT/INOUT 参数值”
【发布时间】:2019-03-04 04:06:52
【问题描述】:

我们正在尝试调用 SQL 服务器过程调用(3 个参数):

ALTER PROCEDURE [mvm].[CHECK_USER]
   @IN_USER char(40),
   @IN_PASS char(40),
   @OUT_OK  int output
AS
BEGIN TRY ...
...
SET @OUT_OK = 0
...
RETURN @OUT_OK (Yes! It has a return)

在 Java Spring Boot 应用程序中,我们将这些添加到 pom.xml

<dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>mssql-jdbc</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

我们在存储库中做了两个方法:

方法一(注解):

@Entity
@NamedStoredProcedureQueries({
    @NamedStoredProcedureQuery(
        name = "CheckUser",
        procedureName = "mvm.CHECK_USER",
        parameters = {
          @StoredProcedureParameter(mode = ParameterMode.IN, /*name = "@IN_USER",*/ type = String.class),
          @StoredProcedureParameter(mode = ParameterMode.IN, /*name = "@IN_PASS",*/ type = String.class),
          @StoredProcedureParameter(mode = ParameterMode.INOUT /*name = "@OUT_OK",*/, type = Long.class  )
        })
})
public class User implements Serializable {

    @Id //To avoid build fail
    private int id; 
}

然后:

public interface TableCheckUser extends CrudRepository<User, Long> {

    @Procedure(name = "CheckUser")
    Long checkUser(String user, String password, Long value);

}

在这种情况下,我们有错误:

org.springframework.dao.InvalidDataAccessApiUsageException: Could not locate parameter registered using that position [4]; nested exception is java.lang.IllegalArgumentException: Could not locate parameter registered using that position [4]

方法 2(书面):

@Repository
public class ProcedureInvoker {

    private final EntityManager entityManager;

    @Autowired
    public ProcedureInvoker(final EntityManager entityManager) {
        this.entityManager = entityManager;
    }
public long getCheckUserValue(String user, String password) {

        StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("mvm.CHECK_USER");


        storedProcedureQuery.registerStoredProcedureParameter(1, String.class, ParameterMode.IN);
        storedProcedureQuery.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
        storedProcedureQuery.registerStoredProcedureParameter(3, Long.class, ParameterMode.INOUT);


        storedProcedureQuery.setParameter(1, user);
        storedProcedureQuery.setParameter(2, password);
        storedProcedureQuery.setParameter(3, new Long(3));

        storedProcedureQuery.execute();

//Another try (with fail) Call to stored procedure [mvm.checkUser] returned no results
        //Object myobj = storedProcedureQuery.getSingleResult();
        //final Long otherlong = (Long) myobj;

        final Long outputValue2 = (Long) storedProcedureQuery.getOutputParameterValue(3);

        return outputValue2; 
    }

我们得到:

2018-09-28 09:36:15.697 TRACE -- [nio-8080-exec-4] o.h.t.d.s.BasicBinder                    : binding parameter [1] as [VARCHAR] - [myuser]
2018-09-28 09:36:15.770 TRACE --- [nio-8080-exec-4] o.h.t.d.s.BasicBinder                    : binding parameter [2] as [VARCHAR] - [mypass]
2018-09-28 09:36:15.844 TRACE --- [nio-8080-exec-4] o.h.t.d.s.BasicBinder                    : binding parameter [3] as [BIGINT] - [3]
2018-09-28 09:36:15.977 DEBUG --- [nio-8080-exec-4] o.h.r.i.OutputsImpl                      : Building Return [isResultSet=false, updateCount=-1, extendedReturn=false
2018-09-28 09:36:17.323 DEBUG --- [l-1 housekeeper] c.z.h.p.HikariPool                       : HikariPool-1 - Pool stats (total=10, active=0, idle=10, waiting=0)
2018-09-28 09:36:22.940 DEBUG --- [nio-8080-exec-4] o.h.e.j.s.SqlExceptionHelper             : Unable to extract OUT/INOUT parameter value [n/a]
com.microsoft.sqlserver.jdbc.SQLServerException: The statement is closed.
    at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:227)
    at com.microsoft.sqlserver.jdbc.SQLServerStatement.checkClosed(SQLServerStatement.java:1014)
    at com.microsoft.sqlserver.jdbc.SQLServerCallableStatement.getLong(SQLServerCallableStatement.java:651)
    at com.zaxxer.hikari.pool.HikariProxyCallableStatement.getLong(HikariProxyCallableStatement.java)

我们尝试了几种方法(添加参数,删除输出参数),但都出错了。

谢谢!

【问题讨论】:

    标签: java sql-server hibernate spring-boot jpa


    【解决方案1】:

    解决了!!

    我不需要 execute() 行。 它仅适用于此:

       StoredProcedureQuery storedProcedureQuery = entityManager.createStoredProcedureQuery("mvm.CHECK_USER");
    
    
            storedProcedureQuery.registerStoredProcedureParameter(1, String.class, ParameterMode.IN);
            storedProcedureQuery.registerStoredProcedureParameter(2, String.class, ParameterMode.IN);
            storedProcedureQuery.registerStoredProcedureParameter(3, Long.class, ParameterMode.INOUT);
    
    
            storedProcedureQuery.setParameter(1, user);
            storedProcedureQuery.setParameter(2, password);
            storedProcedureQuery.setParameter(3, new Long(3));
    
            Long outputValue2 = (Long) storedProcedureQuery.getOutputParameterValue(3);
    

    【讨论】:

    • 谢谢。我敲了 4 个小时的头
    【解决方案2】:

    Approach1 为我工作

    create or replace PROCEDURE test222(x IN   VARCHAR2, y IN   VARCHAR2, z OUT   VARCHAR2
    )
    AS             
    BEGIN
    dbms_output.put_line ('Welcome ');
    insert into person values (x,y);
    z := x;
    END test222;
    
    
    @NamedStoredProcedureQueries({
            @NamedStoredProcedureQuery(name = "test222", procedureName = "test222",
                    parameters = {
                            @StoredProcedureParameter(mode = ParameterMode.IN, name = "x", type = String.class),
                            @StoredProcedureParameter(mode = ParameterMode.IN, name = "y", type = String.class),
                            @StoredProcedureParameter(mode = ParameterMode.OUT, name = "z", type = String.class)
                    }
            )
    })
    
    @Entity
    @Table(name = "Test")
    public class Test implements Serializable 
    
    public interface TestRepository extends CrudRepository<Test, Long> {
    
    
        @Procedure
        String test222(String x, String y);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-14
      • 2011-07-29
      • 2018-12-12
      • 2017-12-15
      • 1970-01-01
      • 2016-07-27
      • 2014-07-27
      • 1970-01-01
      相关资源
      最近更新 更多