【问题标题】:JPA (Hibernate) with MS SQL server 2012/2014 generating incorrect query; no parameter markersJPA (Hibernate) 与 MS SQL server 2012/2014 生成不正确的查询;没有参数标记
【发布时间】:2017-11-05 18:05:47
【问题描述】:

我在使用 MS SQL 2012 的休眠方言时遇到问题。我有一个使用 org.h2.Driver 正常工作的过滤器,它告诉我我有 org.springframework.data.jpa.domain.Specification<T> 定义正确。

H2方言返回查询:

SELECT
    requesthea0_.DIG_REQUEST_ID            AS DIG_REQU1_3_,
    requesthea0_.ASSIGNEE                  AS ASSIGNEE8_3_,
    requesthea0_.COMMENT                   AS COMMENT2_3_,
    requesthea0_.CREATED_BY                AS CREATED_9_3_,
    requesthea0_.CREATED_DATE              AS CREATED_3_3_,
    requesthea0_.DECLINE_ID                AS DECLINE10_3_,
    requesthea0_.DEPARTMENT_ID             AS DEPARTM11_3_,
    requesthea0_.EMERGENCY_FLAG            AS EMERGENC4_3_,
    requesthea0_.LOCATION_ID               AS LOCATIO12_3_,
    requesthea0_.MODIFIED_BY               AS MODIFIE13_3_,
    requesthea0_.MODIFIED_DATE             AS MODIFIED5_3_,
    requesthea0_.PRIORITY_ID               AS PRIORIT14_3_,
    requesthea0_.REQUESTED_COMPLETION_DATE AS REQUESTE6_3_,
    requesthea0_.RESOLUTION_ID             AS RESOLUT15_3_,
    requesthea0_.STATUS_ID                 AS STATUS_16_3_,
    requesthea0_.TITLE                     AS TITLE7_3_
FROM
    DBO.DIG_REQUEST requesthea0_
LEFT OUTER JOIN
    DBO.DIG_PICK_LISTS requestpri1_
ON
    requesthea0_.PRIORITY_ID=requestpri1_.ID
LEFT OUTER JOIN
    DBO.DIG_PICK_LISTS requeststa2_
ON
    requesthea0_.STATUS_ID=requeststa2_.ID
WHERE
    requesthea0_.STATUS_ID IN (?)
ORDER BY
    requesthea0_.REQUESTED_COMPLETION_DATE ASC,
    requestpri1_.ID ASC,
    requeststa2_.ID ASC,
    requesthea0_.DIG_REQUEST_ID ASC limit ?

而使用 org.hibernate.dialect.SQLServer2012Dialect 创建一个查询:

SELECT TOP(?) 
    requesthea0_.DIG_REQUEST_ID            AS DIG_REQU1_3_,
    requesthea0_.ASSIGNEE                  AS ASSIGNEE8_3_,
    requesthea0_.COMMENT                   AS COMMENT2_3_,
    requesthea0_.CREATED_BY                AS CREATED_9_3_,
    requesthea0_.CREATED_DATE              AS CREATED_3_3_,
    requesthea0_.DECLINE_ID                AS DECLINE10_3_,
    requesthea0_.DEPARTMENT_ID             AS DEPARTM11_3_,
    requesthea0_.EMERGENCY_FLAG            AS EMERGENC4_3_,
    requesthea0_.LOCATION_ID               AS LOCATIO12_3_,
    requesthea0_.MODIFIED_BY               AS MODIFIE13_3_,
    requesthea0_.MODIFIED_DATE             AS MODIFIED5_3_,
    requesthea0_.PRIORITY_ID               AS PRIORIT14_3_,
    requesthea0_.REQUESTED_COMPLETION_DATE AS REQUESTE6_3_,
    requesthea0_.RESOLUTION_ID             AS RESOLUT15_3_,
    requesthea0_.STATUS_ID                 AS STATUS_16_3_,
    requesthea0_.TITLE                     AS TITLE7_3_
FROM
    DBO.DIG_REQUEST requesthea0_
LEFT OUTER JOIN
    DBO.DIG_PICK_LISTS requestpri1_
ON
    requesthea0_.PRIORITY_ID=requestpri1_.ID
LEFT OUTER JOIN
    DBO.DIG_PICK_LISTS requeststa2_
ON
    requesthea0_.STATUS_ID=requeststa2_.ID
WHERE
    requesthea0_.STATUS_ID IN ()
ORDER BY
    requesthea0_.REQUESTED_COMPLETION_DATE ASC,
    requestpri1_.ID ASC,
    requeststa2_.ID ASC,
    requesthea0_.DIG_REQUEST_ID ASC

没有参数标记“?”出于某种原因。

这是在 MS SQL 服务器上,用于Select @@version 返回

Microsoft SQL Server 2012 - 11.0.2100.60 (X64)   Feb 10 2012 19:39:15   Copyright (c) Microsoft Corporation  Express Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)

我有两个 mssql 依赖项:

<dependency>
  <groupId>com.microsoft.sqlserver</groupId>
  <artifactId>mssql-jdbc</artifactId>
  <version>6.1.0.jre7</version>
</dependency>
<dependency>
  <groupId>com.microsoft.sqlserver</groupId>
  <artifactId>sqljdbc4</artifactId>
  <version>4.0</version>
  <scope>runtime</scope>
</dependency>

示例堆栈跟踪:

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1692)
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1602)
    at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:492)
    at org.hibernate.jpa.criteria.compile.CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:50)
    ...
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95)
    ... 162 common frames omitted

更新:为了完整起见,我还尝试将 net.sourceforge.jtds.jdbc.Driver 作为备用驱动程序,但仍然遇到相同的错误。

啊哈,控制台出现了另一个错误。我们未能获取 ManyToOne 孩子,然后 JPA 显然不知道如何处理 NULL:

    org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [SELECT ID, LIST_NAME, SHORT_TEXT, LONG_TEXT, SEQUENCE, ALTERNATE_SEQUENCE FROM dbo.DIG_PICK_LISTS WHERE ID = ?]; SQL state [null]; error code [0]; The requested operation is not supported on forward only result sets.; nested exception is com.microsoft.sqlserver.jdbc.SQLServerException: The requested operation is not supported on forward only result sets.

所以根本问题是 JDBC extractData 方法使用了 SqlServer 不支持的 ResultSet.first() 方法。

@Override
            public PickListItem extractData(ResultSet rs) throws SQLException, DataAccessException
            {

                PickListItem pickListItem = new PickListItem();
                rs.first();
                pickListItem.setId(rs.getLong("ID"));
                pickListItem.setListName(rs.getString("LIST_NAME"));
                pickListItem.setShortText(rs.getString("SHORT_TEXT"));
                pickListItem.setLongText(rs.getString("LONG_TEXT"));
                pickListItem.setSequence(rs.getDouble("SEQUENCE"));
                pickListItem.setAlternateSequence(rs.getDouble("ALTERNATE_SEQUENCE"));
                return PickListSubTypeFactory.createSubType(pickListItem);
            }

【问题讨论】:

    标签: java sql-server spring hibernate jpa


    【解决方案1】:

    在这种情况下,只需将 rs.first() 替换为 rs.next() 即可解决 SqlServer 的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-11
      • 1970-01-01
      • 1970-01-01
      • 2014-09-23
      • 2016-02-17
      • 2016-04-18
      相关资源
      最近更新 更多