JPA(Hibernate)与MS SQL服务器2012/2014生成不正确的查询;没有参数标记

时间:2017-11-05 18:05:47

标签: java sql-server spring hibernate jpa

我遇到了MS SQL 2012的hibernate方言的问题。我有一个使用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

没有参数标记&#34;?&#34;出于某种原因。

这是在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);
            }

1 个答案:

答案 0 :(得分:0)

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