1

我们有一个 Spring Boot 应用程序,我们需要连接到 Oracle DB 并通过存储过程获取数据。我们的每个存储过程都有REF_CURSOROUT 参数。我正在尝试相同的使用@NamedStoredProcedureQuery@Entity注释。我们正在使用ojdbc14.jarinpom.xmlOracle12cDialectinapplication.properties文件。我在执行我的代码时收到异常Invalid Column Name 。同样在实体类中,我必须引入一个带有 annotation 的字段,尽管我的存储过程@Id没有返回这样的字段。REF_CURSOR这会是个问题吗?同样不定义@Id字段也不是一个选项,因为 Hibernate 会抛出异常。任何提示将不胜感激。

实现和问题与通过 JPA 2.1 调用带有 ref_cursor 的 Oracle 存储过程时的问题 Invalid column name exception 非常相似

但是那里没有发布答案

4

1 回答 1

0

如何实现它的简单示例:

  1. 数据库架构。
create table MY_PATIENT
(
   PAT_RECID  number,
   PAT_NAME varchar2(100),
   
   constraint PAT_PK primary key(PAT_RECID)
);

create table MY_ORDER
(
   ORD_RECID  number,
   ORD_CODE varchar2(15),
   ORD_PATID number,
   
   constraint ORD_PK primary key(ORD_RECID),
   constraint ORD_PAT_FK foreign key(ORD_PATID) references MY_PATIENT(PAT_RECID),
   constraint ORD_CODE_UNIQUE unique (ORD_CODE)
);

CREATE OR REPLACE PROCEDURE fetch_patient_orders(
  patientId IN NUMBER, 
  patientOrders OUT SYS_REFCURSOR)
AS
BEGIN
   OPEN patientOrders FOR
   SELECT *
   FROM MY_ORDER
   WHERE ORD_PATID = patientId;
END;
  1. 实体定义。
@NamedStoredProcedureQueries(
   @NamedStoredProcedureQuery(
      name = "fetch_patient_orders",
      procedureName = "fetch_patient_orders",
      resultClasses = Order.class, 
      parameters = {
         @StoredProcedureParameter(
            name = "patientId",
            type = Long.class,
            mode = ParameterMode.IN
         ),
         @StoredProcedureParameter(
            name = "patientOrders",
            type = Class.class,
            mode = ParameterMode.REF_CURSOR
         )
      }
   )
)
@Entity
@Table(name = "MY_ORDER")
public class Order
{
   @Id
   @Column(name = "ORD_RECID")
   private Long id;
   
   @Column(name = "ORD_CODE")
   private String code;

   @ManyToOne
   @JoinColumn(name = "ORD_PATID")
   private Patient patient;
}
  1. 和用法:
List<Order> orders = session.createNamedStoredProcedureQuery("fetch_patient_orders")
    .setParameter("patientId", 2L)
    .getResultList();

用hibernate 5.4.12.Final, ojdbc8.jar,测试过Oracle12cDialect。另请参阅休眠文档

上述方法适用于纯休眠应用程序,但不适用于 Spring Boot 应用程序。

根据弹簧启动文档

连接到生产数据库

生产数据库连接也可以使用 pooling 自动配置DataSource。Spring Boot 使用以下算法来选择特定的实现:

  1. 我们更喜欢HikariCP的性能和并发性。如果 HikariCP 可用,我们总是选择它。

  2. 否则,如果 Tomcat 池化 DataSource 可用,我们就使用它。

  3. 如果 HikariCP 和 Tomcat 池数据源都不可用,并且Commons DBCP2可用,我们就使用它。

如果你使用spring-boot-starter-jdbcor spring-boot-starter-data-jpa“starters”,你会自动获得对 HikariCP 的依赖。

spring.datasource.type您可以完全绕过该算法并通过设置属性来指定要使用的连接池。

所以,spring boot 默认使用 HikariCP JDBC 连接池。而且看起来REF_CURSOR参数注册有问题:

o.h.r.j.i.ResourceRegistryStandardImpl   : Registering statement [HikariProxyCallableStatement@770201936 wrapping oracle.jdbc.driver.OracleCallableStatementWrapper@528a6369]
o.h.type.descriptor.sql.BasicBinder      : binding parameter [patientId] as [BIGINT] - [2]
o.h.s.i.AbstractServiceRegistryImpl      : Initializing service [role=org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport]
o.h.engine.jdbc.spi.SqlExceptionHelper   : Error registering REF_CURSOR parameter [patientOrders] [n/a]

当我在以下位置使用 oracle 特定数据源池时application.properties

# com.zaxxer.hikari.HikariDataSource (default value)
spring.datasource.type=oracle.jdbc.pool.OracleDataSource

一切正常。

于 2020-04-04T15:47:16.380 回答