HQL查询中的休眠表未映射错误

Posted

技术标签:

【中文标题】HQL查询中的休眠表未映射错误【英文标题】:Hibernate table not mapped error in HQL query 【发布时间】:2013-01-04 22:40:53 【问题描述】:

我有一个使用 Hibernate 对数据库进行 CRUD 操作的 Web 应用程序。我收到一个错误,说该表未映射。查看 Java 文件:

错误信息:

org.springframework.orm.hibernate3.HibernateQueryException: Books is not mapped [SELECT COUNT(*) FROM Books]; nested exception is org.hibernate.hql.ast.QuerySyntaxException: Books is not mapped [SELECT COUNT(*) FROM Books]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:660)
at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
...
Caused by: org.hibernate.hql.ast.QuerySyntaxException: Books is not mapped [SELECT COUNT(*) FROM Books]
at org.hibernate.hql.ast.util.SessionFactoryHelper.requireClassPersister(SessionFactoryHelper.java:181)
at org.hibernate.hql.ast.tree.FromElementFactory.addFromElement(FromElementFactory.java:111)
at org.hibernate.hql.ast.tree.FromClause.addFromElement(FromClause.java:93)
...

这是我的DAO.java 方法:

public int getTotalBooks()
    return DataAccessUtils.intResult(hibernateTemplate.find(
          "SELECT COUNT(*) FROM Books"));

Book.java:

@Entity
@Table(name="Books")
public class Book 

    @Id
    @GeneratedValue
    @Column(name="id")
    private int id;

    @Column(name="title", nullable=false)
    private String title;
    ...

我应该如何修改它才能工作?

【问题讨论】:

什么是持久化类的包名? 请重新表述,我不明白你的想法 请填写班级名称。问题可能与表名的定义有关。请检查两个地方是否使用相同的名称。 (区分大小写) 【参考方案1】:

在 Spring 配置错误 applicationContext.xml 中配置的 sessionFactory 放置了这个属性

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="packagesToScan" value="$package.name"/>

【讨论】:

我不知道包名是什么,所以我把上下文属性作为它的名字 现在是:但它不起作用.. extjs.model.Books 应该在那里,而不是在属性中,而是在包中 不工作:原因:org.hibernate.hql.ast.QuerySyntaxException:书籍未映射[从书籍中选择计数(*)],现在是: 因为你的班级名为 Book 而不是 Books【参考方案2】:

异常消息说:

Books is not mapped [SELECT COUNT(*) FROM Books]; nested exception is org.hibernate.hql.ast.QuerySyntaxException: Books is not mapped [SELECT COUNT(*) FROM Books]

Books 未映射。也就是说,没有称为Books 的映射类型。

事实上,没有。您的映射类型称为Book。它映射到名为Books 的表,但类型名为Book。当您编写 HQL(或 JPQL)查询时,您使用的是类型的名称,而不是表。

所以,将您的查询更改为:

select count(*) from Book

虽然我认为可能需要

select count(b) from Book b

如果 HQL 不支持 * 表示法。

【讨论】:

这不起作用,请参阅错误:Caused by: org.hibernate.hql.ast.QuerySyntaxException: Books is not mapped [select count(*) from Books] 现在我明白你在说什么了,我很着急,所以我只是快速阅读所有答案......我的错。我现在将尝试从 Books 更改为 Book。我认为你是对的 对我来说,这里的关键点是:在您的 HQL 中,您必须使用实体名称而不是表名称。这一切都不同了。 当然它说它没有映射但是错误并且你没有说如何进行映射。 不要混用表名和存储库名。您的休眠查询针对存储库【参考方案3】:

谢谢大家。很多好主意。 这是我在 Spring 和 Hibernate 中的第一个应用程序.. 所以在与像我这样的“新手”打交道时要多一点耐心..

请阅读 Tom Anderson 和 Roman C. 的答案。他们很好地解释了这个问题。你们都帮了我。我换了

SELECT COUNT(*) FROM Books

select count(book.id) from Book book

当然,我有这个 Spring 配置:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan" value="extjs.model"/>

再次感谢大家!

【讨论】:

这如何添加到您参考的答案中?复制他们的信息并不能真正帮助页面作为参考。 我不明白你的意思是什么,我没有创建这个答案来获得更多的支持。我创建了所有答案的综合。如您所见,这不是公认的答案。我的答案是 2013 年的,你的答案是 2016 年的。所以你说我的答案是多余的?抱歉,您正在寻找赞成票。 不,不是在寻找赞成票@pascut。只是想确保没有重复的信息。几乎每个问题都有多个答案,但我倾向于要求人们考虑删除,如果他们没有添加任何新内容并且稍后出现。 感谢您的好意。我相信我的回答也为这个问题增加了很好的价值。【参考方案4】:

hibernate3.HibernateQueryException: Books is not mapped [SELECT COUNT(*) FROM Books];

Hibernate 试图说它不知道名为“Books”的实体。让我们看看你的实体:

@javax.persistence.Entity
@javax.persistence.Table(name = "Books")
public class Book 

没错。 Booktable 名称已重命名为“Books”,但实体名称仍是类名称中的“Book”。如果要设置实体名称,则应使用 @Entity 注释的名称:

// this allows you to use the entity Books in HQL queries
@javax.persistence.Entity(name = "Books")
public class Book 

设置实体名和表名。


当我从Person.hbm.xml 文件迁移到使用Java 注释来描述休眠字段时,我遇到了相反的问题。我的旧 XML 文件有:

<hibernate-mapping package="...">
    <class name="Person" table="persons" lazy="true">
       ...
</hibernate-mapping>

我的新实体有一个@Entity(name=...),我需要用它来设置表的名称。

// this renames the entity and sets the table name
@javax.persistence.Entity(name = "persons")
public class Person 
    ...

然后我看到的是 HQL 错误,例如:

QuerySyntaxException: Person is not mapped
     [SELECT id FROM Person WHERE id in (:ids)]

问题在于实体名称也被重命名为persons。我应该使用以下方法设置表名:

// no name = here so the entity can be used as Person
@javax.persistence.Entity
// table name specified here
@javax.persistence.Table(name = "persons")
public class Person extends BaseGeneratedId 

【讨论】:

【参考方案5】:

这个答案来晚了,但总结了“表未映射”异常中涉及的概念(为了帮助那些遇到这个问题的人,因为它对于休眠新手来说很常见)。由于许多原因,可能会出现此错误,但目标是解决许多新手休眠开发人员面临的最常见错误,以节省他们数小时的研究时间。下面我用我自己的例子做一个简单的演示。

例外:

org.hibernate.hql.internal.ast.QuerySyntaxException: subscriber is not mapped [ from subscriber]

简单来说,这个非常常见的异常只说明下面代码中的查询是错误的。

Session session = this.sessionFactory.getCurrentSession();
List<Subscriber> personsList = session.createQuery(" from subscriber").list();

这就是我的 POJO 类的声明方式:

@Entity
@Table(name = "subscriber")
public class Subscriber

但是查询语法"fromsubscriber" 是正确的并且表subscriber 存在。这让我想到了一个关键点:

这是一个 HQL 查询而不是 SQL。

以及它的explained here

HQL 适用于持久对象及其属性,而不适用于数据库表和列。

由于上述查询是 HQL 查询,subscriber 应该是实体名称而不是表名称。因为我的表subscriber 与实体Subscriber 映射。如果我把代码改成这样,我的问题就解决了:

Session session = this.sessionFactory.getCurrentSession();
List<Subscriber> personsList = session.createQuery(" from Subscriber").list();

只是为了不让您感到困惑。请注意,HQL 在许多情况下都区分大小写。否则它会在我的情况下工作。

SELECT、FROM 和 WHERE 等关键字不区分大小写,但 在 HQL 中,表名和列名等属性区分大小写。

https://www.tutorialspoint.com/hibernate/hibernate_query_language.htm

要进一步了解休眠映射的工作原理,请阅读this

【讨论】:

【参考方案6】:

Hibernate 对大小写也很挑剔。默认情况下,它将是第一个字母大写的类名。因此,如果您的班级名为FooBar,请不要通过"foobar"。您必须通过 "FooBar" 与它的确切大小写才能工作。

【讨论】:

【参考方案7】:

除了接受的答案之外,另一项检查是确保在设置会话工厂时正确引用 sessionFactory.setPackagesToScan(...) 中的实体包。

【讨论】:

【参考方案8】:

确保你有实体注解和表注解,并在表注解上设置表名。

@Entity
@Table(name = "table_name")
public class TableName 


【讨论】:

正是我的情况:我有 @Entity(name = "table_name") 但没有 @Table 注释。在我将其更改为@Entity @Table(name = "table_name") 后,它起作用了。注意:不必为@Entity 注释指定(name = "table_name")【参考方案9】:

我有同样的问题,而不是@Entity 我使用以下代码获取记录

    List<Map<String, Object>> list = null;
            list = incidentHibernateTemplate.execute(new HibernateCallback<List<Map<String, Object>>>() 

            @Override
            public List<Map<String, Object>> doInHibernate(Session session) throws HibernateException 
                Query query = session.createSQLQuery("SELECT * from table where appcode = :app");
                    query.setParameter("app", apptype);
                query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
                return query.list();

                
            );

我使用以下代码进行更新

private @Autowired HibernateTemplate incidentHibernateTemplate;
Integer updateCount = 0;

    updateCount = incidentHibernateTemplate.execute((Session session) -> 
        Query<?> query = session
                    .createSQLQuery("UPDATE  tablename SET key = :apiurl, data_mode = :mode WHERE apiname= :api ");
          query.setParameter("apiurl", url);
          query.setParameter("api", api);
          query.setParameter("mode", mode);
            return query.executeUpdate();
        
    );

【讨论】:

以上是关于HQL查询中的休眠表未映射错误的主要内容,如果未能解决你的问题,请参考以下文章

带有外连接的休眠 HQL 查询

JPQL 构造函数表达式 - org.hibernate.hql.ast.QuerySyntaxException:表未映射

休眠前 N 行 HQL 查询

无法从 Hibernate 工具执行简单的 HQL 查询

java Java的:休眠:查询:HQL

即使在 HQL 查询中使用 Join Fetch,休眠延迟初始化异常