【问题标题】:could not extract ResultSet in hibernate无法在休眠中提取 ResultSet
【发布时间】:2013-12-04 00:54:26
【问题描述】:

休眠有问题。我尝试解析为 List 但它引发异常:HTTP Status 500 - could not extract ResultSet。当我调试时,它在query.list() 行出错...

我的示例代码在这里

@Entity
@Table(name = "catalog")
public class Catalog implements Serializable {

@Id
@Column(name="ID_CATALOG")
@GeneratedValue 
private Integer idCatalog;

@Column(name="Catalog_Name")
private String catalogName;

@OneToMany(mappedBy="catalog", fetch = FetchType.LAZY)
private Set<Product> products = new HashSet<Product>(0);

//getter & setter & constructor
//...
}


@Entity
@Table(name = "product")
public class Product implements Serializable {

@Id
@Column(name="id_product")
@GeneratedValue 
private Integer idProduct;

@ManyToOne
@JoinColumn(name="ID_CATALOG")
private Catalog catalog;

@Column(name="product_name")
private String productName;

@Column(name="date")
private Date date;

@Column(name="author")
private String author;

@Column(name="price")
private Integer price;

@Column(name="linkimage")
private String linkimage;

//getter & setter & constructor
}



@Repository
@SuppressWarnings({"unchecked", "rawtypes"})
public class ProductDAOImpl implements ProductDAO {
    @Autowired
    private SessionFactory sessionFactory;
public List<Product> searchProductByCatalog(String catalogid, String keyword) {
    String sql = "select p from Product p where 1 = 1";
    Session session = sessionFactory.getCurrentSession();

    if (keyword.trim().equals("") == false) {
        sql += " and p.productName like '%" + keyword + "%'";
    }
    if (catalogid.trim().equals("-1") == false
            && catalogid.trim().equals("") == false) {
        sql += " and p.catalog.idCatalog = " + Integer.parseInt(catalogid);
    }
    Query query = session.createQuery(sql);
    List listProduct = query.list();
    return listProduct;
}

}

我的豆子

  <!-- Scan classpath for annotations (eg: @Service, @Repository etc) -->
  <context:component-scan base-package="com.shopmvc"/>

  <!-- JDBC Data Source. It is assumed you have MySQL running on localhost port 3306 with 
       username root and blank password. Change below if it's not the case -->
  <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/shoesshopdb?autoReconnect=true"/>
    <property name="username" value="root"/>
    <property name="password" value="12345"/>
    <property name="validationQuery" value="SELECT 1"/>
  </bean>

  <!-- Hibernate Session Factory -->
  <bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan">
      <array>
        <value>com.shopmvc.pojo</value>
      </array>
    </property>
    <property name="hibernateProperties">
      <value>
        hibernate.dialect=org.hibernate.dialect.MySQLDialect
      </value>
    </property>
  </bean>

  <!-- Hibernate Transaction Manager -->
  <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="mySessionFactory"/>
  </bean>

  <!-- Activates annotation based transaction management -->
  <tx:annotation-driven transaction-manager="transactionManager"/>

例外:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:948)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:728)

root cause 

org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:82)
    org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:61)
    org.hibernate.loader.Loader.getResultSet(Loader.java:2036)

root cause 

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'product0_.ID_CATALOG' in 'field list'
    sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    java.lang.reflect.Constructor.newInstance(Unknown Source)
    com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    com.mysql.jdbc.Util.getInstance(Util.java:386)
    com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
    com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
    com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
    com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
    com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
    com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
    com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2322)
    org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
    org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
    org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:56)
    org.hibernate.loader.Loader.getResultSet(Loader.java:2036)
    org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1836)
    org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1815)
    org.hibernate.loader.Loader.doQuery(Loader.java:899)
    org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:341)
    org.hibernate.loader.Loader.doList(Loader.java:2522)
    org.hibernate.loader.Loader.doList(Loader.java:2508)
    org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2338)
    org.hibernate.loader.Loader.list(Loader.java:2333)
    org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:490)

我的数据库:

CREATE TABLE `catalog` (
  `ID_CATALOG` int(11) NOT NULL AUTO_INCREMENT,
  `Catalog_Name` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`ID_CATALOG`)
)

CREATE TABLE `product` (
  `id_product` int(11) NOT NULL AUTO_INCREMENT,
  `product_name` varchar(45) DEFAULT NULL,
  `date` date DEFAULT NULL,
  `author` varchar(45) DEFAULT NULL,
  `price` int(11) DEFAULT NULL,
  `catalog_id` int(11) DEFAULT NULL,
  `linkimage` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`id_product`),
  KEY `FK_Product_idx` (`catalog_id`),
  CONSTRAINT `FK_Product` FOREIGN KEY (`catalog_id`) REFERENCES `catalog` (`ID_CATALOG`) ON DELETE NO ACTION ON UPDATE NO ACTION
)

【问题讨论】:

    标签: java sql hibernate spring-mvc


    【解决方案1】:

    尝试在查询中使用内部联接

        Query query=session.createQuery("from Product as p INNER JOIN p.catalog as c 
        WHERE c.idCatalog= :id and p.productName like :XXX");
        query.setParameter("id", 7);
        query.setParameter("xxx", "%"+abc+"%");
        List list = query.list();
    

    在hibernate配置文件中也有

    <!--hibernate.cfg.xml -->
    <property name="show_sql">true</property>
    

    在控制台上显示正在查询的内容。

    【讨论】:

      【解决方案2】:

      @JoinColumn 注释指定用作目标实体的外键的列的名称。

      在上面的Product 类上,连接列的名称设置为ID_CATALOG

      @ManyToOne
      @JoinColumn(name="ID_CATALOG")
      private Catalog catalog;
      

      但是,Product 表上的外键称为catalog_id

      `catalog_id` int(11) DEFAULT NULL,
      

      您需要更改表格上的列名或@JoinColumn 中使用的名称,以便它们匹配。见http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html/entity.html#entity-mapping-association

      【讨论】:

        【解决方案3】:

        我有类似的问题。尝试使用 HQL 编辑器。它将向您显示 SQL(因为您有 SQL 语法异常)。复制您的 SQL 并单独执行它。就我而言,问题出在模式定义中。我定义了架构,但我应该将其留空。这引发了与您得到的相同的异常。并且错误描述反映了实际状态,因为架构名称包含在 SQL 语句中。

        【讨论】:

          【解决方案4】:

          对于遇到相同错误消息的其他人来说,另一个潜在原因是,如果您正在访问与您已通过身份验证的表不同的架构中的表,则会发生此错误。

          在这种情况下,您需要将架构名称添加到您的实体条目中:

          @Table(name= "catalog", schema = "targetSchemaName")
          

          【讨论】:

          • 当我尝试创建新的 sboot -mysql -jpa 应用程序时发生这种情况。没有创建 db 表。这解决了我的问题。
          • 或者当表名不匹配时...比如@Table(name = "catalog", schema = "taretSchemaName"),表名是taretSchemaName
          【解决方案5】:

          如果您没有在数据库中创建 'HIBERNATE_SEQUENCE' 序列(如果使用 oracle 或任何基于序列的数据库),您将得到相同类型的错误;

          确保序列存在;

          【讨论】:

          • 您能详细说明一下吗?
          • 如果您使用的是 oracle DB 并禁用了自动模式创建,您可能也缺少序列 HIBERNATE_SEQUENCE。如果这是您的情况,您可以尝试将生成的值注释更改为其他内容,例如:@GeneratedValue(strategy=GenerationType.IDENTITY) 如果您是 ofc,则使用列上的标识生成 id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY,
          【解决方案6】:

          在将数据库从在线服务器迁移到本地主机后,我遇到了同样的问题。架构发生了变化,因此我必须为每个表手动定义架构:

          @Entity
          @Table(name = "ESBCORE_DOMAIN", schema = "SYS")
          

          【讨论】:

            【解决方案7】:

            另一种解决方案是添加 @JsonIgnore :

            @OneToMany(mappedBy="catalog", fetch = FetchType.LAZY)
            @JsonIgnore
            private Set<Product> products = new HashSet<Product>(0);
            

            【讨论】:

            • 解释一下这将如何解决问题哥们。通过了解解决方案,寻求答案的人会受益更多。
            【解决方案8】:

            我在 application.properties 文件中使用了以下属性,问题得到解决

            spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
            

            spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
            

            之前出错了

            There was an unexpected error (type=Internal Server Error, status=500).
            could not extract ResultSet; SQL [n/a]; nested exception is 
            org.hibernate.exception.SQLGrammarException: could not extract ResultSet
            org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
            at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:280)
            at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:254)
            at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:528)
            at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
            at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
            at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
            at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
            

            【讨论】:

            • 我想这是(有时更好)替代上面建议的使用 @Table(name= "catalog", schema = "targetSchemaName") 显式注释的方法。更好,因为当您从 EE 应用程序复制代码时,您不必修改实体类。
            【解决方案9】:

            当我尝试更新一行时,我遇到了同样的问题:

            @Query(value = "UPDATE data SET value = 'asdf'", nativeQuery = true)
            void setValue();
            

            我的问题是我忘记添加@Modifying 注释:

            @Modifying    
            @Query(value = "UPDATE data SET value = 'asdf'", nativeQuery = true)
            void setValue();
            

            【讨论】:

              【解决方案10】:

              我在 PostgreSql 中使用 Spring Data JPA,在 UPDATE 调用期间它显示错误-

              • '无法提取 ResultSet' 和另一个。
              • org.springframework.dao.InvalidDataAccessApiUsageException:正在执行 更新/删除查询;嵌套异常是 javax.persistence.TransactionRequiredException:执行一个 更新/删除查询。 (显示需要交易。

              实际上,我缺少两个必需的注释。

              • @Transactional 和
              • @Modifying

              有-

              @Query(vlaue = " UPDATE DB.TABLE SET Col1 = ?1 WHERE id = ?2 ", nativeQuery = true)
              void updateCol1(String value, long id);
              

              【讨论】:

                【解决方案11】:

                对于MySql,请记住编写camelcase 不是一个好主意。 例如,如果架构是这样的:

                CREATE TABLE IF NOT EXISTS `task`(
                    `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
                    `teaching_hours` DECIMAL(5,2) DEFAULT NULL,
                    `isActive` BOOLEAN DEFAULT FALSE,
                    `is_validated` BOOLEAN DEFAULT FALSE,
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
                
                

                您必须非常小心,因为isActive 列将转换为isactive。 所以在你的 Entity 类中应该是这样的:

                 @Basic
                 @Column(name = "isactive", nullable = true)
                 public boolean isActive() {
                     return isActive;
                 }
                 public void setActive(boolean active) {
                     isActive = active;
                 }
                

                这是我的问题,至少让我犯了你的错误

                这与不区分大小写的 MySql 无关,而是 spring 用于翻译您的表的命名策略。 更多请参考post

                【讨论】:

                  【解决方案12】:

                  如果您错误地为您的表使用了保留关键字 (https://dev.mysql.com/doc/refman/8.0/en/keywords.html#keywords-8-0-detailed-C),也会出现此消息。当在一个名为 sama 作为保留的 mysql 关键字的表上进行连接时,您将收到相同的消息,尽管其他一切都是正确的。 希望这会为其他人节省一些时间和痛苦。

                  【讨论】:

                    【解决方案13】:

                    我已经重现了类似的问题:

                    Caused by: org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
                        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:279)
                        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253)
                        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
                        at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
                        at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
                    
                    ...
                    
                    Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'setting0_.advance_payment_first_text' in 'field list'
                        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120)
                        at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
                        at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
                        at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:975)
                        
                    

                    在我的特定用例中,这是因为用于数据库的新转储与 liquibase 配置文件 data.xml 之间的冲突,逻辑如下:

                    <changeSet  author="liquibase-docs"  id="sqlFile-data">
                            <sqlFile  dbms="!h2, oracle, mysql"
                                      encoding="UTF-8"
                                      path="..\..\..\sql\data.sql"
                                      relativeToChangelogFile="true"
                                      splitStatements="true"
                                      stripComments="true"/>
                    </changeSet>
                    

                    structure.xml:

                    <changeSet  author="liquibase-docs"  id="sqlFile-structure">
                            <sqlFile  dbms="!h2, oracle, mysql"
                                      encoding="UTF-8"
                                      path="..\..\..\sql\structure.sql"
                                      relativeToChangelogFile="true"
                                      splitStatements="true"
                                      stripComments="true"/>
                    </changeSet>
                    

                    用于项目的旧脚本。

                    通过检查代码中的表与列的对应关系进行了一些调查后,我了解到这些旧脚本在运行项目新转储后被覆盖。

                    因此,在从项目中删除带有配置文件 data.xmlstructure.xml 的旧脚本 data.sqlstructure.sql 后,这个问题就解决了。

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-05-06
                      • 2015-08-03
                      • 2016-09-28
                      • 2018-10-04
                      • 2014-08-31
                      • 1970-01-01
                      相关资源
                      最近更新 更多