Hibernate混合存储过程输出参数

Hibernate混合存储过程输出参数,hibernate,jpa,stored-procedures,oracle11g,wildfly,Hibernate,Jpa,Stored Procedures,Oracle11g,Wildfly,在工作中,我们遇到了一个似乎无法解决的问题 我们正在使用Wilfly 10、Hibernate 5.0.0.Final和带有存储过程的Oracle 11g数据库。我还想指出,Hibernate4上的Wilfly9也出现了同样的问题,因此我认为这可能是一个奇怪的问题,我想知道以前是否有人遇到过这个问题 无论何时调用存储过程,Hibernate(使用JPA2.1API)都会以一致的方式混合输出参数。让我给你举个例子: public ProcedureResult submitApplication(

在工作中,我们遇到了一个似乎无法解决的问题

我们正在使用Wilfly 10、Hibernate 5.0.0.Final和带有存储过程的Oracle 11g数据库。我还想指出,Hibernate4上的Wilfly9也出现了同样的问题,因此我认为这可能是一个奇怪的问题,我想知道以前是否有人遇到过这个问题

无论何时调用存储过程,Hibernate(使用JPA2.1API)都会以一致的方式混合输出参数。让我给你举个例子:

public ProcedureResult submitApplication(Long stageId) {
    StoredProcedureQuery query = em.createStoredProcedureQuery("qu_utl_java.submit_application");
    query.registerStoredProcedureParameter("p_ase_id", Long.class, ParameterMode.IN);
    query.registerStoredProcedureParameter("p_bypass_communication", String.class, ParameterMode.IN);
    query.registerStoredProcedureParameter("p_id", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_result", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_error_message", String.class, ParameterMode.OUT);

    query.setParameter("p_ase_id", stageId);
    query.setParameter("p_bypass_communication", "N");
    query.execute();

    ProcedureResult result = new ProcedureResult();
    result.setExecutionResult((String) query.getOutputParameterValue("p_result"));
    result.setResultID((String) query.getOutputParameterValue("p_id"));
    result.setErrorMessage((String) query.getOutputParameterValue("p_error_message"));

    return result;
}
在上面的代码中,您希望p_result参数最终出现在setExecutionResult()中。然而,这并没有发生。此参数在setResultID()中结束。尽管它们是命名参数,但它们会混淆,但方式非常一致

我们可以通过调整代码来解决这个问题,因为它在所有环境中都是持久的,可以通过切换输出参数名称来匹配正确的名称。然而,我们不想这样做,因为这是一个非常丑陋的解决方案

我还应该注意到,当我们从JBoss5(我们正在从它迁移)调用这个过程时,一切都很好。这些参数最终位于正确的变量中,因此不应归咎于该过程。我们也在pl/sqldeveloper中测试了这一点

并不是每次通话都会出现这种情况,只是有些通话会出现这种情况,但在发生的通话中,这种情况是一致的。我还尝试了普通的hibernate实现,而不是JPAAPI,但结果是一样的

这是我们的持久性文件:

<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
         xsi:schemaLocation="
    http://xmlns.jcp.org/xml/ns/persistence
    http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="CENSORED">
        <jta-data-source>java:jboss/datasources/CENSORED</jta-data-source>
        <properties>
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

我希望有人遇到了同样的问题并找到了解决办法,或者如果我们能找到解决办法并帮助其他人。非常感谢您的帮助,谢谢

对于将来遇到此问题的任何人,以下是解决方案。我不知道这是Hibernate中的一个bug还是有意的,但如果这是您的oracle过程定义:

 procedure submit_application(p_ase_id                in qu_applications_stage.id%type,
                           p_id                    out varchar2,
                           p_result                out varchar2,
                           p_error_message         out varchar2,
                           p_bypass_communication  in  varchar2 default null);
然后,您应该按照该顺序设置参数!在我的例子中,我将最后一个参数作为第二个参数,因此所有输出参数都会移位

这是代码修复:

public ProcedureResult submitApplication(Long stageId) {
    StoredProcedureQuery query = em.createStoredProcedureQuery("qu_utl_java.submit_application");
    query.registerStoredProcedureParameter("p_ase_id", Long.class, ParameterMode.IN);
    query.registerStoredProcedureParameter("p_id", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_result", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_error_message", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_bypass_communication", String.class, ParameterMode.IN);

    query.setParameter("p_ase_id", stageId);
    query.setParameter("p_bypass_communication", "N");
    query.execute();

    ProcedureResult result = new ProcedureResult();
    result.setExecutionResult((String) query.getOutputParameterValue("p_result"));
    result.setResultID((String) query.getOutputParameterValue("p_id"));
    result.setErrorMessage((String) query.getOutputParameterValue("p_error_message"));

    return result;
}

我将与Hibernate确认这是有意的还是一个bug。谢谢大家的意见

是否有out参数返回为null?是的。这可能是问题所在吗?好吧,这与空参数或其他任何东西无关。这与您注册参数的顺序有关!它的顺序应该与oracle包中定义的顺序相同。非常奇怪,因为这些都是命名参数,但实际上注册它们的顺序是绝对必要的!哈实际上,订购问题是我要去的地方。你可能想在HHH JIRA上开一张罚单,看看他们的反应,但据我所知,顺序一直是预期的行为。
public ProcedureResult submitApplication(Long stageId) {
    StoredProcedureQuery query = em.createStoredProcedureQuery("qu_utl_java.submit_application");
    query.registerStoredProcedureParameter("p_ase_id", Long.class, ParameterMode.IN);
    query.registerStoredProcedureParameter("p_id", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_result", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_error_message", String.class, ParameterMode.OUT);
    query.registerStoredProcedureParameter("p_bypass_communication", String.class, ParameterMode.IN);

    query.setParameter("p_ase_id", stageId);
    query.setParameter("p_bypass_communication", "N");
    query.execute();

    ProcedureResult result = new ProcedureResult();
    result.setExecutionResult((String) query.getOutputParameterValue("p_result"));
    result.setResultID((String) query.getOutputParameterValue("p_id"));
    result.setErrorMessage((String) query.getOutputParameterValue("p_error_message"));

    return result;
}