Retrieving Lists of Entities from a Database Using Hibernate
Hibernate is a powerful Object-Relational Mapping (ORM) framework for Java that simplifies the interaction between an application and a database through a powerful object-oriented API. One of the most common operations in any database-driven application is to fetch a list of entities. This article will explore various techniques for retrieving entity lists in Hibernate.
1. Mapping Database Tables to Entities
Before exploring the techniques for retrieving entities, it is crucial to understand how Hibernate maps database tables to Java entities. This mapping enables Hibernate to translate between database rows and Java objects seamlessly.
1.1 Entity Class Example
To illustrate, let’s define an entity class that maps to a database table. Consider a simple table book
with columns id
, title
, and author
.
CREATE TABLE book ( id BIGINT AUTO_INCREMENT PRIMARY KEY, title VARCHAR(255), author VARCHAR(255) );
The corresponding Java entity class Book
would look like this:
@Entity public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; private String author; // Getters and Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } }
Explanation:
- @Entity: This annotation specifies that the class is an entity and is mapped to a database table.
- @Id: This annotation specifies the primary key of the entity.
- @GeneratedValue: This annotation provides the specification of generation strategies for the primary key values.
- Long id: This field maps to the
id
column in thebook
table. - String title: This field maps to the
title
column in thebook
table. - String author: This field maps to the
author
column in thebook
table.
Hibernate uses these annotations to understand how the class and its fields relate to the corresponding database table and columns. Once the entity class is defined and mapped, Hibernate can handle the conversion between database rows and Java objects.
When a query is executed using HQL, Criteria API, or native SQL, Hibernate uses these mappings to convert the query into SQL statements that the database understands. It translates Java-based queries into SQL, retrieves the result set, and then maps the result back into Java objects.
2. Setting Up Hibernate
Add the following dependencies in your pom.xml
if you are using Maven:
<dependencies> <dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> <version>5.6.4.Final</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-spatial</artifactId> <version>5.6.4.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.27</version> </dependency> </dependencies>
2.1 Configuring Hibernate with persistence.xml
We can configure Hibernate using the persistence.xml
file, which is part of the Jakarta Persistence API (JPA) standard. This file should be placed in the src/main/resources/META-INF
directory.
2.1.1 Directory Structure
Here’s the typical structure of a Maven project with the persistence.xml
file in the correct location:
Here’s an example of what the content might look like:
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1"> <persistence-unit name="example-unit"> <class>com.jcg.model.Book</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> <property name="hibernate.connection.driver_class" value="com.mysql.cj.jdbc.Driver"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/yourdatabase"/> <property name="hibernate.connection.username" value="yourusername"/> <property name="hibernate.connection.password" value="yourpassword"/> <property name="hibernate.hbm2ddl.auto" value="none"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>
With this setup complete, let’s explore various techniques for retrieving lists of entities.
3. Using JPQL (Java Persistence Query Language)
JPQL uses a syntax similar to SQL, but instead of working with tables and columns, it works with entities and their attributes. This makes the queries easier to read and build.
Example:
public class JPQLExample { public static void main(String[] args) { // Load configuration and build EntityManagerFactory EntityManagerFactory emf = Persistence.createEntityManagerFactory("example-unit"); // Obtain EntityManager and start transaction EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // JPQL query to retrieve all books List<Book> bookList = em.createQuery("SELECT b FROM Book b", Book.class).getResultList(); // Print the result for (Book book : bookList) { System.out.println("Book ID: " + book.getId() + ", Title: " + book.getTitle() + ", Author: " + book.getAuthor()); } // Commit transaction and close EntityManager em.getTransaction().commit(); em.close(); emf.close(); } }
In this example, we obtain an EntityManager instance to interact with the persistence context. The JPQL query string SELECT b FROM Book b
instructs Hibernate to select all Book
entities from the database. We create a query object using em.createQuery
and specify the JPQL string and the expected result type (Book.class
). The getResultList()
method executes the query and returns a list of Book
objects.
4. Criteria API
The Criteria API uses an object-oriented method to build queries. It leverages Java classes and methods to express query logic, making it ideal for dynamic queries.
Example:
public class CriteriaAPIExample { public static void main(String[] args) { // Load configuration and build EntityManagerFactory EntityManagerFactory emf = Persistence.createEntityManagerFactory("example-unit"); // Obtain EntityManager and start transaction EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // Create CriteriaBuilder and CriteriaQuery CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery<Book> criteriaQuery = criteriaBuilder.createQuery(Book.class); // Define the root of the query Root<Book> root = criteriaQuery.from(Book.class); criteriaQuery.select(root); // Execute the query and get the result list List<Book> bookList = em.createQuery(criteriaQuery).getResultList(); // Print the result for (Book book : bookList) { System.out.println("Book ID: " + book.getId() + ", Title: " + book.getTitle() + ", Author: " + book.getAuthor()); } // Commit transaction and close EntityManager em.getTransaction().commit(); em.close(); emf.close(); } }
In this example, we use the Criteria API to build and execute a query to retrieve all Book
objects from the database. After obtaining an EntityManager instance, a CriteriaBuilder
is used to create criteria objects. We define a CriteriaQuery
specifying the result type (Book.class
). The from
method establishes the root entity (Book
). Finally, the criteria query is converted to a standard query using em.createQuery
and executed with getResultList
.
5. Native SQL Queries
For specific database functionalities or performance optimizations, Hibernate allows the execution of raw SQL queries.
Example:
public class NativeSQLExample { public static void main(String[] args) { // Load configuration and build EntityManagerFactory EntityManagerFactory emf = Persistence.createEntityManagerFactory("example-unit"); // Obtain EntityManager and start transaction EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); // Native SQL query to retrieve all books List<Book> books = em.createNativeQuery("SELECT * FROM book").getResultList(); // Print the result for (Book book : books) { System.out.println("Book ID: " + book.getId() + ", Title: " + book.getTitle() + ", Author: " + book.getAuthor()); } // Commit transaction and close EntityManager em.getTransaction().commit(); em.close(); emf.close(); } }
In this example, we use a native SQL query SELECT * FROM book
to fetch all records from the book
table. The query is executed with getResultList
to retrieve a list of Book
objects.
6. Accessing the Collection of Associated Entities from the Parent Entity
In many cases, entities have relationships with other entities, such as one-to-many or many-to-many associations. Hibernate provides a straightforward way to access collections of associated entities from the parent entity. For example, Let’s extend our Book
entity to include a collection of Review
entities. Assume we have a Review
table and entity defined as follows:
CREATE TABLE review ( id BIGINT AUTO_INCREMENT PRIMARY KEY, book_id BIGINT, content TEXT, FOREIGN KEY (book_id) REFERENCES book(id) );
6.1 Review
Entity Class
@Entity public class Review implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String content; @ManyToOne @JoinColumn(name = "book_id") private Book book; // Getters and Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Book getBook() { return book; } public void setBook(Book book) { this.book = book; } }
6.2 Update Book
Entity Class
Add a collection of Review
entities to the Book
class:
@Entity public class Book implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String title; private String author; @OneToMany(mappedBy = "book", cascade = CascadeType.ALL, fetch = FetchType.EAGER) private List<Review> reviews; // Getters and Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public List<Review> getReviews() { return reviews; } public void setReviews(List<Review> reviews) { this.reviews = reviews; } }
In the above example, the @OneToMany
relationship is configured with fetch = FetchType.EAGER
, therefore the associated entity will be fetched immediately with the parent entity.
6.2.1 Example of Fetch Book with Reviews
Let’s examine an example demonstrating how to use parameterized JPQL queries to fetch an entity by a specific criterion and access its associated collections. We will fetch the related reviews using the getReviews
method.
public class FetchBookByTitle { public static void main(String[] args) { // Load configuration and build EntityManagerFactory EntityManagerFactory emf = Persistence.createEntityManagerFactory("example-unit"); // Obtain EntityManager and start transaction EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); try { // JPQL query to fetch book by title String jpql = "SELECT b FROM Book b WHERE b.title = :title"; TypedQuery<Book> query = em.createQuery(jpql, Book.class); query.setParameter("title", "The Great Gatsby"); // Get single result Book book = query.getSingleResult(); // Print the book details System.out.println("Book ID: " + book.getId() + ", Title: " + book.getTitle() + ", Author: " + book.getAuthor()); // Print the associated reviews List<Review> reviews = book.getReviews(); for (Review review : reviews) { System.out.println("Review ID: " + review.getId() + ", Content: " + review.getContent()); } } catch (Exception e) { } finally { // Commit transaction and close EntityManager em.getTransaction().commit(); em.close(); emf.close(); } } }
In this example, we fetch a Book
entity along with its associated Review
entities. The JPQL query SELECT b FROM Book b WHERE b.title = :title
is defined to fetch a book by its title. The :title
parameter is a placeholder for the actual title value. The setParameter
method is used to set the value of the title
parameter. In this case, it’s set to "The Great Gatsby"
. The getSingleResult()
method is used to execute the query and retrieve a single Book
entity. The getReviews
method of the Book
entity is called to retrieve the list of associated Review
entities.
7. Conclusion
Retrieving lists of entities from a database is a common operation in any application using Hibernate. We have explored three different techniques. Each technique has its advantages and use cases, and understanding these will help you choose the right approach for your specific needs. With the provided examples and explanations, you should now be able to retrieve lists of entities from your database using Hibernate effectively.
8. Download the Source Code
This was an article on using Java hibernate to fetch an entity List.
You can download the full source code of this example here: Java Hibernate fetch entity list