如何使用 EclipseLink 2.6 JPA 将表对象类型作为 IN 参数传递到存储过程

问题描述 投票:0回答:1

有人可以帮我弄清楚如何使用 EclipseLink JPA 将表对象类型作为 IN 参数传递给存储过程吗?

这是我的存储过程:

create or replace TYPE FORMS_DTLS_TYPE FORCE as OBJECT
(ITEM_ID  NUMBER, STUDY_ID NUMBER, ITEMTYPE VARCHAR2(50),ITEM_TITLE   VARCHAR2(50));
create or replace TYPE FORMS_DTLS_COLL AS TABLE OF FORMS_DTLS_TYPE;

PROCEDURE createForm(pi_form_coll IN FORMS_DTLS_COLL,
                        x_return_status OUT NOCOPY VARCHAR2)
IS
BEGIN
x_return_status := 'SUCCESS';
FOR i in pi_form_coll.FIRST..pi_form_coll.LAST
LOOP
  INSERT INTO TEST_FORMS ("ITEM_ID", "STUDY_ID", "ITEM_TYPE",  "ITEM_TITLE")
  VALUES (pi_form_coll(i).ITEM_ID,   pi_form_coll(i).STUDY_ID,pi_form_coll(i).ITEMTYPE, 'TITLE');
  COMMIT;
 END LOOP;
END createForm;

使用@NamedPLSQLStoredProcedureQuery定义存储过程:

@Entity
@NamedPLSQLStoredProcedureQueries( {   
 @NamedPLSQLStoredProcedureQuery(name = "TestForms.forms", procedureName = "FORMS_DTLS_PKG.createForm",
            parameters = {
                @PLSQLParameter(name = "pi_form_dtls", direction = Direction.IN, databaseType = "FORMS_DTLS_COLL"),
                @PLSQLParameter(name = "x_return_status", direction = Direction.OUT, databaseType = "VARCHAR_TYPE")
            }
    )
})

@Struct(name="FORMS_DTLS_TYPE", fields={"ITEM_ID", "STUDY_ID", "ITEMTYPE", "ITEM_TITLE"})
@PLSQLTable(
   name="FORMS_DTLS_COLL",
   compatibleType="FORMS_DTLS_TYPE"
)
public class TestForms implements Serializable {
...
}

调用存储过程:

public String createTestForm0() throws ServiceException {
    Query query = em.createNamedQuery("TestForms.forms");
    TestForms forms = new TestForms();
    List<TestForms> formList = new ArrayList();                
    forms.setItemId(BigDecimal.valueOf(5));
    forms.setStudyId(BigInteger.valueOf(99));// stuId);
    forms.setItemType("New");
    forms.setItemTitle("New title");
    formList.add(forms);
    query.setParameter("pi_form_dtls", formList);                
    String result = (String)query.getSingleResult();
    return result;
}

我收到以下错误:

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.4.v20160829-44060b6): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLException: Fail to construct descriptor: Unable to resolve type: "ORACLE.FORMS_DTLS_TYPE"
Error Code: 17060
Call: 
DECLARE
  pi_form_dtlsTARGET FORMS_DTLS_COLL;
  pi_form_dtlsCOMPAT FORMS_DTLS_TYPE := :1;
  x_return_statusTARGET VARCHAR(255);
  FUNCTION EL_SQL2PL_1(aSqlItem FORMS_DTLS_TYPE)
  RETURN FORMS_DTLS_COLL IS
    aPlsqlItem FORMS_DTLS_COLL;
  BEGIN
    IF aSqlItem.COUNT > 0 THEN
      FOR I IN 1..aSqlItem.COUNT LOOP
    aPlsqlItem(I) := aSqlItem(I);
  END LOOP;
END IF;
    RETURN aPlsqlItem;
  END EL_SQL2PL_1;
BEGIN
  pi_form_dtlsTARGET := EL_SQL2PL_1(pi_form_dtlsCOMPAT);
  FORMS_DTLS_PKG.createForm2(pi_form_dtls=>pi_form_dtlsTARGET, x_return_status=>x_return_statusTARGET);
  :2 := x_return_statusTARGET;
END;
  bind => [:1 => [oracle.hsgbu.eclinical.designer.dto.TestFormDto@424d058a], x_return_status => :2]
Query: DataReadQuery(name="TestForms.forms" )
jpa stored-procedures eclipselink
1个回答
0
投票

使用 EclipseLink 2.6 JPA 将表对象类型作为 IN 参数传递给存储过程的方法。这种方法涉及直接使用

java.sql.Struct
java.sql.Array
。方法如下:

  1. 创建一个
    java.sql.Struct
    对象来表示 Oracle 数据库中的对象类型。
Struct struct = connection.createStruct("OBJECT_TYPE_NAME", new Object[] {"value1", "value2", "value3"});
  1. 创建一个表示表类型的
    java.sql.Array
    对象。该对象应包含
    Struct
    对象的数组。
Array array = connection.createArrayOf("TABLE_TYPE_NAME", new Struct[] {struct});
  1. 在存储过程调用中使用这些对象作为参数。
StoredProcedureQuery query = em.createStoredProcedureQuery("MY_STORED_PROCEDURE");
query.registerStoredProcedureParameter(1, Array.class, ParameterMode.IN);
query.setParameter(1, array);
query.execute();

请将

OBJECT_TYPE_NAME
TABLE_TYPE_NAME
MY_STORED_PROCEDURE
替换为您实际的 Oracle 对象类型名称、表类型名称和存储过程名称。

此方法需要一个

java.sql.Connection
对象。您可以从
EntityManager
:

获取一份
java.sql.Connection connection = em.unwrap(java.sql.Connection.class);

请注意,此方法绕过 JPA 并直接使用 JDBC。如果 JPA 提供程序不支持您正在使用的 Oracle 特定类型,则可能有必要。

© www.soinside.com 2019 - 2024. All rights reserved.