Ошибка отображения таблицы Hibernate в HQL-запросе
У меня есть веб-приложение, которое использует Hibernate для выполнения операций CRUD над базой данных. Я получил сообщение о том, что таблица не сопоставлена. Смотрите файлы 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
Что говорит сообщение об исключении? В нем говорится:
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 не поддерживает нотацию *
.
Вы можете учиться на чтении сообщений об исключениях!
Ответ 2
hibernate3.HibernateQueryException: Books is not mapped [SELECT COUNT(*) FROM Books];
Hibernate пытается сказать, что он не знает сущности с именем "Книги". Давайте посмотрим на вашу сущность:
@javax.persistence.Entity
@javax.persistence.Table(name = "Books")
public class Book {
Правильно. Имя таблицы для Book
было переименовано в "Книги", но имя сущности по-прежнему является "Книгой" из имени класса. Если вы хотите установить имя объекта, вы должны использовать вместо него имя аннотации @Entity
:
// this allows you to use the entity Books in HQL queries
@javax.persistence.Entity(name = "Books")
public class Book {
Это устанавливает как имя объекта, так и имя таблицы.
Противоположная проблема возникла со мной, когда я Person.hbm.xml
файла 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 {
Надеюсь, что это помогает другим.
Ответ 3
Этот ответ приходит поздно, но суммирует концепцию, участвующую в исключении "table not mapping" (чтобы помочь тем, кто сталкивается с этой проблемой, поскольку она очень распространена для новичков спящего режима). Эта ошибка может появиться по многим причинам, но целью является решение наиболее распространенной проблемы, с которой сталкиваются многие начинающие разработчики спящего режима, чтобы сохранить их в течение нескольких часов исследований. Я использую свой собственный пример для простой демонстрации ниже.
Исключение:
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
Но синтаксис запроса "от абонента верен, а таблица subscriber
существует. Это подводит меня к ключевому моменту:
- Это запрос HQL, а не SQL.
и как описывается здесь
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
Ответ 4
Спасибо всем. Много хороших идей.
Это мое первое приложение в Spring и Hibernate.. так немного больше терпения при работе с "новичками", как я..
Пожалуйста, прочитайте ответы Тома Андерсона и Романа К. Они очень хорошо объяснили эту проблему. И все вы помогли мне. Я заменил
SELECT COUNT(*) FROM Books
с
select count(book.id) from Book book
И, конечно, у меня есть этот Spring config:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan" value="extjs.model"/>
Еще раз спасибо!
Ответ 5
В конфигурации Spring typo applicationContext.xml
, где сконфигурированное sessionFactory
помещает это свойство
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan" value="${package.name}"/>
Ответ 6
Hibernate также требователен к капитализации. По умолчанию это будет имя класса с первой буквой заглавной. Так что если ваш класс называется FooBar
, не передавайте "foobar"
. Вы должны передать "FooBar"
с точной заглавной буквы, чтобы он работал.
Ответ 7
В дополнение к принятому ответу, еще одна проверка должна убедиться, что у вас есть правильная ссылка на ваш пакет сущностей в sessionFactory.setPackagesToScan(...) при настройке фабрики сеансов.