Hibernate Tutorial

Core Hibernate

Hibernate Mapping

Hibernate Annotations

Hibernate with Spring Framework

Hibernate with Database

Hibernate Log4j

Inheritance Mapping

Hibernate - Mapping List

Mapping a list (java.util.List) in Hibernate lets you represent an ordered collection of elements or entity associations. The order can be materialized through an additional index column or the order in which elements appear in the database.

In this tutorial, we'll see how to map a list in Hibernate.

Example Scenario:

Consider an entity Book which contains multiple Chapter entities in a specific order.

1. Database Tables:

  • book table: To store book details.
  • chapter table: To store chapter details. It will also have a foreign key (book_id) referring to the book table and an index column (chapter_order) to maintain the order.

2. Setting Up Dependencies:

Ensure Hibernate's dependencies are in your project. If you're using Maven, you'll primarily include hibernate-core.

3. Mapping Entities:

Book.java:

@Entity
@Table(name="book")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="title")
    private String title;

    @OneToMany(cascade = CascadeType.ALL)
    @OrderColumn(name="chapter_order")
    @JoinColumn(name="book_id")
    private List<Chapter> chapters = new ArrayList<>();

    // constructors, getters, setters...
}

Chapter.java:

@Entity
@Table(name="chapter")
public class Chapter {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="name")
    private String name;

    // No need to define the book reference here, unless you want it to be bidirectional

    // constructors, getters, setters...
}

Explanation:

  • @OneToMany: This annotation indicates a one-to-many relationship.
  • @OrderColumn: This annotation tells Hibernate to maintain the order of the list based on the specified column (chapter_order in our case).
  • @JoinColumn: This indicates the foreign key column.

4. Working with Data:

Saving:

Session session = sessionFactory.getCurrentSession();
session.beginTransaction();

// create a book and chapters
Book tempBook = new Book("My Book");

Chapter tempChapter1 = new Chapter("Introduction");
Chapter tempChapter2 = new Chapter("Content");

// associate chapters with the book
tempBook.getChapters().add(tempChapter1);
tempBook.getChapters().add(tempChapter2);

// save the book (this will also save the chapters due to CascadeType.ALL)
session.save(tempBook);

session.getTransaction().commit();

Retrieving:

Session session = sessionFactory.getCurrentSession();
session.beginTransaction();

// fetch book with id=1
Book tempBook = session.get(Book.class, 1);

// print chapters of the book (they should be in order)
for(Chapter tempChapter : tempBook.getChapters()) {
    System.out.println(tempChapter.getName());
}

session.getTransaction().commit();

Conclusion:

Mapping a list in Hibernate ensures that you have an ordered collection in your Java application that mirrors the order present in the database. This is particularly useful when the order of elements is significant, like chapters in a book or steps in a tutorial.

However, always keep in mind that managing lists, especially in many-to-many relationships, can have some overhead due to the index column. If the order isn't important, consider using other collection types like Set.

  1. Mapping lists in Hibernate entities:

    • Lists in Hibernate entities are typically used to represent ordered collections of elements.
    • Use the @ElementCollection annotation for mapping lists.
    @ElementCollection
    @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "phone_number")
    private List<String> phoneNumbers;
    
  2. Configuring list mapping with Hibernate annotations:

    • Configure list mapping using the @ElementCollection and @CollectionTable annotations to specify the table and column details.
    @ElementCollection
    @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "phone_number")
    private List<String> phoneNumbers;
    
  3. Lazy loading with Hibernate list mapping:

    • Lazy loading allows the loading of the list elements only when they are accessed.
    • Use fetch = FetchType.LAZY to enable lazy loading.
    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "phone_number")
    private List<String> phoneNumbers;
    
  4. Bidirectional list mapping in Hibernate:

    • Bidirectional list mapping involves having a reference in both entities.
    • Use mappedBy attribute in the @OneToMany or @ManyToMany annotation to establish bidirectional mapping.
    // In Employee class
    @ElementCollection
    @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "phone_number")
    private List<String> phoneNumbers;
    
    // In PhoneNumber class (if needed)
    @ManyToOne
    @JoinColumn(name = "employee_id")
    private Employee employee;
    
  5. Cascading operations in Hibernate list mapping:

    • Cascading allows propagating operations (save, update, delete) from one entity to its associated entities.
    • Use cascade attribute in the @ElementCollection annotation.
    @ElementCollection(cascade = CascadeType.ALL)
    @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "phone_number")
    private List<String> phoneNumbers;
    
  6. Indexing elements in Hibernate list mapping:

    • Indexing allows specifying the order of elements in the list.
    • Use @OrderColumn annotation to indicate the column that will store the index.
    @ElementCollection
    @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "phone_number")
    @OrderColumn(name = "phone_index")
    private List<String> phoneNumbers;
    
  7. HQL queries for list mapping in Hibernate:

    • Use HQL (Hibernate Query Language) to perform queries involving list mapping.
    String hql = "SELECT e.phoneNumbers FROM Employee e WHERE e.id = :employeeId";
    List<String> phoneNumbers = session.createQuery(hql)
       .setParameter("employeeId", 1L)
       .getResultList();
    
  8. Handling orphan removal with Hibernate list mapping:

    • Orphan removal ensures that elements removed from the list are also removed from the database.
    • Use orphanRemoval = true in the @ElementCollection annotation.
    @ElementCollection(cascade = CascadeType.ALL, orphanRemoval = true)
    @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id"))
    @Column(name = "phone_number")
    private List<String> phoneNumbers;