【问题标题】:Execute database function with JPA使用 JPA 执行数据库功能
【发布时间】:2018-06-20 17:21:44
【问题描述】:

要调用 Oracle 数据库函数,我只需编写

final Query query = entityManager.createNativeQuery(
    "select myfunction(?) from dual"
);
query.setParameter(1, "value");
Object rv = query.getSingleResult();

只要被调用的函数不执行任何 dml 操作,它就可以工作。 否则我必须执行类似

    {? = call myfunction(?)}

很遗憾,我无法注册任何 OUT 参数,因此我无法让此语句正常工作。 如果不使用普通的 JDBC,我怎样才能做到这一点?


编辑:

这个问题具有误导性。我想在 Oracle 数据库中获取函数(不是存储过程)的结果。没有 OUT 参数。该函数可能如下所示:

CREATE OR REPLACE FUNCTION myfunction(value IN VARCHAR2)
RETURN VARCHAR2
IS
BEGIN
    UPDATE foo SET bar = 'foobar'
    WHERE id = 1;

    RETURN 'test';
END myfunction;

Calling an oracle function from JPA 的答案并没有解决我的问题,因为我的函数内部有 dml 更改。我收到一个错误:

无法在查询中执行 DML 操作

【问题讨论】:

  • @anste 你是怎么解决的。我陷入了同样的问题
  • @Ismail 不幸的是我没有解决这个问题。我尽可能将函数更改为带有 OUT 参数的过程。或者,您可以创建一个包装过程,该过程调用该函数并将结果放入一个输出参数中。
  • @anste 我解决了。我没有找到任何使用 JPA 的解决方案,所以我不得不使用 JDBC CallableStatement。我会把它添加到答案中

标签: java hibernate jpa entitymanager


【解决方案1】:

您必须使用 StoredProcedureQuery:

StoredProcedureQuery query = this.em.createStoredProcedureQuery("myfunction");
query.registerStoredProcedureParameter("inparam", String.class, ParameterMode.IN);
query.registerStoredProcedureParameter("outparam", String.class, ParameterMode.OUT);

// set input parameter
query.setParameter("inparam", "Hello);

// call the stored procedure and get the result
query.execute();
String result = (String) query.getOutputParameterValue("sum");

如果您期望一个或多个结果,您可以使用

getSingleResult() or getResultList() 

喜欢在 Query 接口上而不是 getOutputParameterValue()

在此处查找更多信息: https://www.thoughts-on-java.org/call-stored-procedures-jpa-part-2/

【讨论】:

  • 我编辑了我的问题。我想获取函数的返回值,而不是任何 OUT 参数。
  • Query 接口上有getResultList() 和getSingleResult 看看文档docs.oracle.com/javaee/7/api/javax/persistence/…
  • 感谢您的帮助,但我无法正常工作。 Hibernate 总是创建一个像“{call myfunction(?)}”这样的语句。所以需要一个过程,我得到“myfunction 不是一个过程或未定义”。你能举个例子吗?
  • 我相信查询在使用createStoredProcedureCallcreateStoredProcedureQuery 时会转换为"{call myfunction(?)}"。如果您只需要返回,则只需使用createNativeQuery
  • 如果函数包含 DML 操作,则不能使用 SELECT。否则我会写'select myfunction(?) from dual'。
【解决方案2】:
  • 当函数中有任何 DML 语句时,选择查询将不起作用。
    如果没有 DML 语句,那么 SELECT QUERY 是最好和最有效的方法。
  • 如果有 DML 语句,则必须使用接口 CallableStatement。
    当我们在我们的项目中使用 JDBC 时,这是非常先进的,但是对于 Spring Project,即使用 JPA,我们需要从 EntityManager 和 ReturningWork 获取会话。
  Session session = entityManager.unwrap(Session.class);
      CallableStatement callableStatement =  session.doReturningWork(new ReturningWork<CallableStatement>() {
            @Override
            public CallableStatement execute(Connection connection) throws SQLException {
                CallableStatement function = connection.prepareCall(
                        "{ ? = call package_name.function_name(?,?) }");
                function.registerOutParameter(1, Types.INTEGER);
                function.setLong(2, 56);
                function.setString(3,"some text");

                function.execute();
                return function;
            }
        });

        try {
            return callableStatement.getBigDecimal(1);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-06
    • 2022-07-06
    • 2020-07-12
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-05
    相关资源
    最近更新 更多