Hibernate混合存储过程输出参数

时间:2015-11-18 09:37:39

标签: hibernate jpa stored-procedures oracle11g wildfly

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

我们正在使用Wilfly 10,Hibernate 5.0.0.Final和带有存储过程的Oracle 11g数据库。我还要注意,在Hibernate 4上使用Wilfly 9会出现同样的问题,所以我认为这可能是一个奇怪的问题,我想知道是否有人曾经遇到过它。

每当我们调用存储过程时,Hibernate(使用JPA2.1 API)混合输出参数,但是以一致的方式。让我举个例子:

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()中。即使它们被命名为参数,但它们会以非常一致的方式混合。

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

我还应该注意,当我们从Jboss 5(我们正在迁移)调用该过程时,一切正常。参数最终在正确的变量中,所以程序不应该受到责备。我们也在pl / sql开发人员中测试了这个。

每次通话都不会发生这种情况,只有一些情况发生,但在发生这种情况时,它是一致的。我也尝试过普通的hibernate实现而不是JPA api,但结果是一样的。

这是我们的持久性文件:

<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>

它使用正确的方言,因为它在启动日志中显示:

10:06:04,310 INFO  [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 25) HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect

我希望有人遇到同样的问题并找到了解决方法,或者我们是否可以找到解决方案并帮助其他人。感谢您的帮助,谢谢!

1 个答案:

答案 0 :(得分:3)

对于将来遇到此问题的任何人,这是解决方案。我不知道这是当前Hibernate中的错误还是有意,但如果这是你的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是否有意或是错误。感谢您到目前为止的任何输入。