在工作中,我们遇到了一个似乎无法解决的问题。
我们使用的是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实现,而不是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>
它确实使用了正确的方言,因为它在启动日志中显示了这一点:
10:06:04,310 INFO [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 25) HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
我希望有人遇到了同样的问题并找到了解决方案,或者如果我们能找到解决方案并帮助他人。非常感谢您的帮助,谢谢!
对于将来遇到此问题的任何人,以下是解决方案。我不知道这是否是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核实这是否是故意的或是一个错误。谢谢你们到目前为止的任何意见。