【问题标题】:JPA + StoredProcedureCall + object type IN parameterJPA + StoredProcedureCall + 对象类型 IN 参数
【发布时间】:2012-02-26 02:27:11
【问题描述】:

我正在尝试做一件简单的事情:调用具有对象类型参数的存储过程。

这是我在 db 中的:

create or replace
TYPE TEST_TYPE AS OBJECT 
(
  test_field varchar(100)
)

CREATE OR REPLACE PROCEDURE TEST_PROC 
(
  PARAM1 IN TEST_TYPE 
) AS 
BEGIN
END TEST_PROC;

这是我的 java 代码中的内容:

@Embeddable
@Struct(name = "TEST_TYPE", fields = {"TEST_FIELD"})
public class TestStruct
{

    private String testField;

    public String getTestField() {
        return testField;
    }

    public void setTestField(String testField) {
        this.testField = testField;
    }
}

    @PostConstruct
    public void init()
    {

        StoredProcedureCall call = new StoredProcedureCall();
        call.setProcedureName("TEST_PROC");
        call.addNamedArgument("PARAM1", "PARAM1", Types.STRUCT, "TEST_TYPE", TestStruct.class);

        DataReadQuery dataReadQuery = new DataReadQuery(call);
        dataReadQuery.addArgument("PARAM1");

        TestStruct testStruct = new TestStruct();
        List args = new ArrayList();
        args.add(testStruct);

        Object result = ((EntityManagerImpl)em.getDelegate()).getSession().executeQuery(dataReadQuery,args);
    }

这是我在运行时得到的:

Internal Exception: java.sql.SQLException: Invalid column type
Error Code: 17004
Call: BEGIN TEST_PROC(PARAM1=>?); END;
    bind => [1 parameter bound]
Query: DataReadQuery()

我想我完全不明白 JPA 的使用结构的主题

请帮助我,好人:)

实现此功能的最短方法是什么?

【问题讨论】:

    标签: java oracle stored-procedures eclipselink


    【解决方案1】:

    请发送完整的代码。 对于使用 Spring 调用存储过程,您必须扩展 StoredProcedure 类。如果您发送完整的代码,我可以提供更好的帮助。示例伪代码:

    class CustomStoredProcedure extends org.springframework.jdbc.object.StoredProcedure
    {
        CustomStoredProcedure()
        {
            super([your-data-source], [package-name]);  
            declareParameter(new SqlParameter([your-struct-name]), Types.STRUCT));
            compile();
        }
    
        Map<String, Object> execute([your-parameter])
        {
            return super.execute(inputs);
        }
    }
    

    为了更好的帮助,你已经解释了完整的情况。

    【讨论】:

    • 这是完整的情况 - 我只是在测试如何解决 EclipseLink JPA2.0 实现的常见问题。 BTW AFAIK Spring 没有实现 JPA - 我错了吗?
    • 你说的没错,Spring 没有实现 JPA。我不使用 EclipseLink。我的解决方案独立于 jpa 实现,它由 spring 框架提供并且工作正常。如果你只想使用 EclipseLink,你必须阅读它的文档。
    【解决方案2】:

    您的代码看起来正确。

    确保为结构定义了描述符。 (即 session.getDescrptor(TestStruct.class))

    可以调用其他类型的存储过程吗?

    您使用的是什么数据库,您的平台是否正确设置为 Oracle?

    【讨论】:

    • “确保为结构定义了描述符”是否意味着描述符将由于注释而自动创建?最近我尝试手动设置它们:` ObjectRelationalDataTypeDescriptor d = new ObjectRelationalDataTypeDescriptor(); d.setJavaClass(TestStruct.class); d.descriptorIsAggregate(); d.setStructureName("TEST_TYPE"); d.addDirectMapping("TEST_FIELD", "getTestField", "setTestField", "testField"); d.setShouldOrderMappings(false); ((EntityManagerImpl)em.getDelegate()).getServerSession().addDescriptor(d); `
    • 我可以使用简单类型(如 varchar)调用存储过程。我正在使用 Oracle 10 和正确的 jdbc 驱动程序。
    • 描述符应该从注释中创建,但是如果您没有在persistence.xml 中指定类或有其他问题可能没有,因此检查它是一个好主意。当你在代码中定义它时它工作了吗?
    • 不,它没有。我的同事告诉我,他在我们使用的 EclipseLink 库中发现了一些错误
    【解决方案3】:

    似乎 跳过了@Struct@Embeddable 注释类的描述符,除非它们被其他类引用。使其工作的最短方法是使用基于此假设的解决方法。在 META-INF/persistence.xml 所在的 jar 中添加额外的类:

    @Entity
    public class StructEntitiesWorkaround {
    
      @Id
      private String id;
    
      private TestStruct testStruct;
    
    }
    

    【讨论】:

      【解决方案4】:

      您可能希望将SimpleJdbcCallTypes.STRUCT 一起使用。

      这里是一个例子:https://docs.spring.io/spring-data/jdbc/old-docs/2.0.0.M1/reference/html/orcl.datatypes.html

      【讨论】:

        猜你喜欢
        • 2017-06-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多