Hibernate Tutorial
Core Hibernate
Hibernate Mapping
Hibernate Annotations
Hibernate with Spring Framework
Hibernate with Database
Hibernate Log4j
Inheritance Mapping
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.
Consider an entity Book
which contains multiple Chapter
entities in a specific order.
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.Ensure Hibernate's dependencies are in your project. If you're using Maven, you'll primarily include hibernate-core
.
@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... }
@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... }
@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.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();
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();
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
.
Mapping lists in Hibernate entities:
@ElementCollection
annotation for mapping lists.@ElementCollection @CollectionTable(name = "phone_numbers", joinColumns = @JoinColumn(name = "employee_id")) @Column(name = "phone_number") private List<String> phoneNumbers;
Configuring list mapping with Hibernate annotations:
@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;
Lazy loading with Hibernate list mapping:
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;
Bidirectional list mapping in Hibernate:
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;
Cascading operations in Hibernate list mapping:
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;
Indexing elements in Hibernate list mapping:
@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;
HQL queries for list mapping in Hibernate:
String hql = "SELECT e.phoneNumbers FROM Employee e WHERE e.id = :employeeId"; List<String> phoneNumbers = session.createQuery(hql) .setParameter("employeeId", 1L) .getResultList();
Handling orphan removal with Hibernate list mapping:
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;