Last Updated: 

Hibernate 'Books is not mapped' Error in HQL Query: Causes and Step-by-Step Solutions

Hibernate, a popular ORM (Object-Relational Mapping) framework, simplifies database interactions by mapping Java objects (entities) to database tables. One of its key features is HQL (Hibernate Query Language), a SQL-like language used to query entities. However, developers often encounter the frustrating error: "Books is not mapped" (or similar, e.g., "Book is not mapped") when executing HQL queries. This error indicates that Hibernate cannot recognize the entity name referenced in the query, preventing it from translating the HQL into a valid SQL statement.

In this blog, we’ll demystify this error by exploring its root causes and providing actionable, step-by-step solutions to resolve it. Whether you’re a beginner or an experienced developer, this guide will help you diagnose and fix the issue quickly.

Table of Contents#

  1. Understanding the 'Books is not mapped' Error
  2. Common Causes of the Error
  3. Step-by-Step Solutions to Fix the Error
  4. Preventive Measures to Avoid the Error
  5. Summary
  6. References

Understanding the 'Books is not mapped' Error#

The error "Books is not mapped" occurs when Hibernate cannot find a mapped entity with the name specified in your HQL query. HQL operates on entity names (not database table names) to retrieve or manipulate data. If Hibernate does not recognize the entity name in the query, it throws this error to indicate the mismatch.

Example error message:

org.hibernate.hql.internal.ast.QuerySyntaxException: Books is not mapped [FROM Books]

In this case, Hibernate is unable to locate an entity named Books in its mapping metadata. Let’s dive into the common causes of this issue.

Common Causes of the Error#

1. Entity Name Mismatch (Typo, Casing, or Pluralization)#

The most frequent cause is a mismatch between the entity class name (or its mapped name) and the name used in the HQL query. This includes:

  • Typos (e.g., Bookk instead of Book).
  • Incorrect pluralization (e.g., Books instead of Book).
  • Casing issues (HQL is case-sensitive for entity names; e.g., book instead of Book).

Example Scenario:
Suppose you have an entity class named Book:

// Entity class name: "Book"
package com.example.library.entity;
 
import javax.persistence.Entity;
import javax.persistence.Id;
 
@Entity
public class Book {
    @Id
    private Long id;
    private String title;
    // Getters and setters
}

If your HQL query mistakenly uses Books (plural) instead of Book:

String hql = "FROM Books"; // Error: "Books is not mapped"
Query query = session.createQuery(hql);

Hibernate fails to find an entity named Books and throws the error.

2. Missing @Entity Annotation on the Entity Class#

Hibernate only maps classes annotated with @Entity (or XML-configured entities) to database tables. If you forget to add @Entity to your class, Hibernate will not recognize it as an entity, leading to the "not mapped" error.

Example Scenario:
An entity class without @Entity:

// Missing @Entity annotation
package com.example.library.entity;
 
import javax.persistence.Id;
 
public class Book { // Hibernate ignores this class
    @Id
    private Long id;
    private String title;
    // Getters and setters
}

Even if your HQL query uses FROM Book, Hibernate will throw:
org.hibernate.hql.internal.ast.QuerySyntaxException: Book is not mapped.

3. Hibernate/JPA Configuration Issues (Entity Not Scanned)#

Hibernate requires explicit configuration to locate entity classes. If your entities are not in the expected package or not listed in the configuration, Hibernate will not scan them, resulting in unmapped entities.

Common configuration gaps include:

  • JPA persistence.xml: Missing <class> entries for entities or exclude-unlisted-classes set to true (default in JPA).
  • Spring Boot: Entities located in a package not scanned by default (e.g., outside the main application class package).

4. Using Table Name Instead of Entity Name in HQL#

HQL queries reference entity names, not database table names. Even if your entity is mapped to a table with a different name (via @Table), HQL uses the entity’s class name (or custom name) to query data.

Example Scenario:
An entity mapped to table books but queried using the table name:

@Entity
@Table(name = "books") // Entity maps to table "books"
public class Book { // Entity name is "Book"
    @Id
    private Long id;
    private String title;
}

If your HQL query uses the table name books instead of the entity name Book:

String hql = "FROM books"; // Error: "books is not mapped" (uses table name)

5. Custom Entity Name via @Entity(name) Not Used in HQL#

By default, the entity name matches the class name. However, you can define a custom entity name using @Entity(name = "CustomName"). If you use this, HQL queries must reference the custom name, not the class name.

Example Scenario:
An entity with a custom name:

@Entity(name = "LibraryBook") // Custom entity name: "LibraryBook"
public class Book { // Class name is "Book", but entity name is "LibraryBook"
    @Id
    private Long id;
    private String title;
}

If your HQL query uses the class name Book instead of the custom name LibraryBook:

String hql = "FROM Book"; // Error: "Book is not mapped" (uses class name instead of custom name)

Step-by-Step Solutions to Fix the Error#

Solution 1: Verify Entity Name and Correct HQL Query#

Ensure the HQL query uses the exact entity class name (case-sensitive) with no typos or pluralization errors.

Steps:

  1. Check the entity class name (e.g., Book).
  2. Correct the HQL query to use this name.

Example Fix:

// Incorrect: Uses plural "Books"
String hql = "FROM Books"; 
 
// Correct: Uses entity class name "Book"
String hql = "FROM Book"; 
Query query = session.createQuery(hql);
List<Book> books = query.list();

Solution 2: Add the @Entity Annotation to the Entity Class#

Ensure the entity class is annotated with @Entity to tell Hibernate to map it.

Example Fix:

package com.example.library.entity;
 
import javax.persistence.Entity; // Import @Entity
import javax.persistence.Id;
 
@Entity // Add this annotation
public class Book {
    @Id
    private Long id;
    private String title;
    // Getters and setters
}

Solution 3: Configure Hibernate to Scan Entity Packages#

Ensure Hibernate scans your entity classes by updating your configuration.

For JPA persistence.xml:#

If using JPA, explicitly list entities or allow scanning of unlisted classes:

<!-- persistence.xml -->
<persistence-unit name="LibraryPU">
    <!-- Option 1: List entities explicitly -->
    <class>com.example.library.entity.Book</class>
 
    <!-- Option 2: Scan all entities in the classpath (exclude-unlisted-classes=false) -->
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
 
    <properties>
        <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/library"/>
        <property name="hibernate.hbm2ddl.auto" value="update"/>
        <!-- Other properties -->
    </properties>
</persistence-unit>

For Spring Boot:#

If entities are in a non-default package (e.g., com.example.entities instead of com.example.app), use @EntityScan to specify the package:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.boot.autoconfigure.domain.EntityScan;
 
@SpringBootApplication
@EntityScan("com.example.entities") // Scan entities in this package
public class LibraryApplication {
    public static void main(String[] args) {
        SpringApplication.run(LibraryApplication.class, args);
    }
}

Solution 4: Use Entity Name (Not Table Name) in HQL Queries#

HQL queries must reference the entity name, not the database table name. Use the entity class name (or custom name) instead of the table name.

Example Fix:

// Incorrect: Uses table name "books"
String hql = "FROM books"; 
 
// Correct: Uses entity name "Book"
String hql = "FROM Book"; 
Query query = session.createQuery(hql);
List<Book> books = query.list();

Solution 5: Use the Custom Entity Name Defined in @Entity(name)#

If you defined a custom entity name with @Entity(name = "CustomName"), use that name in HQL queries.

Example Fix:

// Entity with custom name
@Entity(name = "LibraryBook") 
public class Book { ... }
 
// Incorrect: Uses class name "Book"
String hql = "FROM Book"; 
 
// Correct: Uses custom entity name "LibraryBook"
String hql = "FROM LibraryBook"; 
Query query = session.createQuery(hql);
List<Book> books = query.list();

Preventive Measures to Avoid the Error#

  1. Validate Entity Names in HQL Queries: Use your IDE’s refactoring tools to ensure consistency between entity class names and HQL references.
  2. Enable IDE Plugins: Tools like Hibernate Tools (Eclipse) or JPA Buddy (IntelliJ) highlight unmapped entity names in HQL.
  3. Unit Test HQL Queries: Write tests to execute HQL queries during development (e.g., using HibernateTestSupport or Spring Boot’s @DataJpaTest).
  4. Document Custom Entity Names: If using @Entity(name), add comments in the entity class to remind developers to use the custom name in HQL.

Summary#

The "Books is not mapped" error in Hibernate HQL queries typically stems from entity name mismatches, missing annotations, configuration gaps, or confusion between entity and table names. By verifying entity names, ensuring proper annotations, configuring Hibernate to scan entities, and using entity names (not table names) in HQL, you can resolve this error efficiently. Adopting preventive measures like IDE validation and unit testing will help avoid similar issues in the future.

References#