web-dev-qa-db-fra.com

Erreur de la table Hibernate non mappée dans une requête HQL

J'ai une application Web qui utilise Hibernate pour effectuer des opérations CRUD sur une base de données. J'ai une erreur en disant que la table n'est pas mappée. Voir les fichiers Java:

Message d'erreur:

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)
...

Voici ma méthode 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;
    ...
}

Comment dois-je le modifier pour fonctionner?

47
Pascut

Que dit le message d'exception? Ça dit:

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

Qu'est-ce que cela vous dit? Il vous dit que Books n'est pas mappé. C'est-à-dire qu'il n'y a pas de type mappé appelé Books.

Et en effet, il n'y en a pas. Votre type mappé s'appelle Book. Il est associé à une table appelée Books, mais le type s'appelle Book. Lorsque vous écrivez des requêtes HQL (ou JPQL), vous utilisez les noms des types, pas les tables.

Alors, changez votre requête en:

select count(*) from Book

Bien que je pense que cela peut être nécessaire

select count(b) from Book b

Si HQL ne prend pas en charge la notation *.

Vous pouvez apprendre beaucoup de choses en lisant des messages d'exception!

98
Tom Anderson

Merci à tous. Beaucoup de bonnes idées ..__ Ceci est ma première application dans Spring et Hibernate ... donc un peu plus de patience lorsque je traite avec des "novices" comme moi ..

Veuillez lire les réponses de Tom Anderson et Roman C. Ils ont très bien expliqué le problème. Et vous m'avez tous aidé. J'ai remplacé 

SELECT COUNT(*) FROM Books

avec

select count(book.id) from Book book

Et bien sûr, j'ai cette config de printemps:

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

Merci encore à tous!

3
Pascut

Cette réponse arrive en retard, mais résume le concept impliqué dans l'exception "table non mappée" (afin d'aider ceux qui rencontrent ce problème car il est très courant pour les débutants en veille prolongée). Cette erreur peut apparaître pour diverses raisons, mais l'objectif est de résoudre le problème le plus courant auquel sont confrontés un certain nombre de développeurs novices en veille prolongée afin de leur épargner des heures de recherche. J'utilise mon propre exemple pour une démonstration simple ci-dessous.

L'éxéption:

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

En termes simples, cette exception très habituelle indique uniquement que la requête est incorrecte dans le code ci-dessous. 

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

Voici comment ma classe POJO est déclarée:

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

Mais la syntaxe de requête "from subscriber" est correcte et la table subscriber existe. Ce qui m'amène à un point clé:

  • C'est une requête HQL, pas SQL.

et comment son expliqué ici

HQL fonctionne avec les objets persistants et leurs propriétés, mais pas avec les tables et les colonnes de la base de données. 

Comme la requête ci-dessus est une requête HQL, la subscriber est supposée être un nom d'entité et non un nom de table. Depuis que ma table subscriber est mappée avec l'entité Subscriber. Mon problème est résolu si je change le code en ceci:

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

Juste pour vous empêcher de vous embrouiller. Veuillez noter que HQL est sensible à la casse dans un certain nombre de cas. Sinon, cela aurait fonctionné dans mon cas.

Les mots clés tels que SELECT, FROM et WHERE, etc. ne sont pas sensibles à la casse, mais les propriétés telles que les noms de table et de colonne sont sensibles à la casse dans HQL.

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

Pour mieux comprendre le fonctionnement de la mise en veille prolongée, veuillez lire this

2
Sibgha

Dans la configuration de printemps typo applicationContext.xml où la sessionFactory configurée met cette propriété

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

Hibernate est également pointilleux sur la capitalisation. Par défaut, ce sera le nom de la classe avec la première lettre en majuscule. Donc, si votre classe s'appelle FooBar, ne transmettez pas "foobar". Vous devez passer "FooBar" avec cette capitalisation exacte pour que cela fonctionne.

0
Jon

En plus de la réponse acceptée, une autre vérification consiste à vous assurer que vous disposez de la référence appropriée à votre package d'entités dans sessionFactory.setPackagesToScan (...) lors de la configuration de votre fabrique de sessions.

0
Durja Arai