【问题标题】:JPA - How to select from a database function?JPA - 如何从数据库函数中进行选择?
【发布时间】:2016-10-05 19:07:53
【问题描述】:

我在 T-SQL 中有以下 SQL 查询:

SELECT a.ReportDate,
    a.Value,
    a.Quantity,
    a.ID,
    a.Code
FROM AQF.fCalc(@data) a

@datavarbinary。我正在尝试使用 JPA 复制此查询。 (我实际上使用的是 Spring Data JPA 1.10.2。)我在MyRepository 中定义了以下内容:

@Query("SELECT a "
        + "FROM function('AQF.fCalc', :data) a "
       )
List<MyClass> getCalcData(@Param("data") byte[] data);

MyClass如下:

@Entity
@Data // using lombok to create setters, getters, etc.
public class MyClass {

    @Id
    private Long id;

    private Date reportDate;
    private BigDecimal value;
    private BigDecimal quantity;
    private String code;

}

当我调用 getCalcData 时,我收到以下错误:

antlr.NoViableAltException: unexpected token: function
at org.hibernate.hql.internal.antlr.HqlBaseParser.fromRange(HqlBaseParser.java:1501) [hibernate-core-5.0.9.Final.jar:5.0.9.Final]...

如何使用 JPA 调用函数 AQF.fCalc(并传入字节数组)?

更新 1

我现在也尝试过使用本机查询,但现在我收到一条错误消息:

java.sql.SQLException: An error occurred while getting new row from user defined Table Valued Function : 
System.Xml.XmlException: Unexpected end of file has occurred. The following elements are not closed: Data, Report. Line 24, position 804.

这是 MyRepository 中原生查询的测试代码:

@Query(value = "SELECT a.code "
        + "FROM AQF.fCalc(?1) a",
       nativeQuery = true)
List<String> getCalcData(byte[] data);

更新 2

我能够解决上面“更新 1”中提到的错误。 getCalcData 中的数据字节数组已损坏。一旦我解决了这个问题,错误就不再出现了。所以,现在我可以作为本机查询运行。不过,我还是想知道如何使用 JPQL 来进行这个函数调用。

【问题讨论】:

  • 这不是有效的 JPQL,因此请尝试将其指定为原生查询 docs.spring.io/spring-data/jpa/docs/current/reference/html/…
  • 好的。感谢您的评论。我引用了这篇文章:我可能误解了一些东西,但根据post,JPQL 似乎支持(自 JPA 2.1 起)这种语法。无论如何,我更改为使用本机查询,现在我没有收到错误,但也没有返回任何结果。
  • 对不起,我发现没有结果的问题。现在,我收到了上述更新帖子中指出的错误。
  • 这是数据库端的一个例外,所以看起来您的函数至少现在正在被调用。感谢您对 JPQL 和函数调用的澄清。 Hibernate 4.3+ 实现了 JPA 2.1,所以如果您的 Hibernate 版本 =>4.3,我希望您的原始(非本机)调用能够正常工作
  • 是的。现在看来,我至少可以使用更新部分中的代码调用 DB 函数。我不确定为什么原始代码不起作用。我正在使用 Spring Data JPA 1.10.2,我认为它正在引入 Hibernate 版本 => 4.3。不确定如何确认?我在我的类路径上看到了 jar hibernate-core-5.0.11.Final.jar。另外,我从 jTds 1.3.1 jar 切换到 Microsoft 的 sqljdbc 4.2。现在我收到一条不同的错误消息`com.microsoft.sqlserver.jdbc.SQLServerException:索引 4 超出范围。索引 4 超出范围。` 后跟

标签: spring hibernate jpa spring-data-jpa


【解决方案1】:

您可以使用 StoredProcedureQuery。来自javadoc

用于控制存储过程查询执行的接口。

请参阅此示例代码。

假设在本例中您的 SQL 函数名称是 sales_tax。

        EntityManager em = factory.createEntityManager();

        // Create call stored procedure
        em.getTransaction().begin();
        StoredProcedureQuery storedProcedure = em.createStoredProcedureQuery("sales_tax");
        // set parameters
        storedProcedure.registerStoredProcedureParameter("subtotal", Double.class, ParameterMode.IN);
        storedProcedure.registerStoredProcedureParameter("tax", Double.class, ParameterMode.OUT);
        storedProcedure.setParameter("subtotal", 1f);
        // execute SP
        storedProcedure.execute();
        // get result
        Double tax = (Double)storedProcedure.getOutputParameterValue("tax");
        System.out.println("Tax is: " + tax);
        em.getTransaction().commit();
        em.close();

【讨论】:

  • 我需要在 select 语句中使用该函数。该函数返回一个表。我看不出存储过程调用将如何工作。
  • function 是 storeprocedure 的别称
  • 如何在 OP 中解决我的问题?该函数返回一个表。我不清楚你将如何定义 out 参数的类型。
  • @James,您找到解决方案了吗?我有同样的问题:(
  • @Hicham,是的,我能够从数据库函数中进行选择。我不得不使用原生查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-17
  • 2012-04-05
  • 2018-10-05
  • 2014-10-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多