Entity Relationship On Hibernate JPA

This article is tested against Java EE 6, Hibernate 4.2.2.

One To Many Unidirectional Relationship

Unidirectional here means you can only obtain related entities from one side. For example supposed we have one to many Customer --> Account relationship, here’s what Customer entity look like


public class Customer {

  @Id
  
  private long id;

  private String name;

  
  (name = "customer_id")
  private Set accounts;

  // getters & setters..
}

Instead of Set, you can use List, however if you have more than one relationship in your entity class, you will get MultipleBagFetchException.

And This is what Account looks like. Notice there’s no reference to Customer object from Account.


public class Account {

  @Id
  
  private long id;
  
  private double balance;

  // Getters & Setters ..
}

One To Many Bidirectional Relationship

Similar to unidirectional except you can obtain relation from both direction. This is what Customer and Account look like:


public class Customer {

  @Id
  
  private long id;

  private String name;

  (mappedBy = "customer")
  private Set accounts;

  // getters & setters..
}

The “customer” on (mappedBy = "customer") refers to customer java property on Account entity.


public class Account {

  @Id
  
  private long id;
  
  private double balance;

  
  (name = "customer_id")
  private Customer customer;

  // Getters & Setters ..
}

The (name = "customer_id") annotation sets the database foreign key column name to be “customer_id”.

Lazy / Eager Loading

Lazy / Eager refers to when does entity relationship get populated. Eager means it will get populated as soon as the entity is obtained from database, where in Lazy it’s only populated when you request the relationship for the first time.

The default value for is LAZY, but for it’s EAGER. It’s a good practice to explicitly configure it so your code is easier to understand


public class Customer {
  ...
  (mappedBy = "customer", fetch = FetchType.LAZY)
  private Set accounts;
  ...
}

public class Account {
  ...
  (fetch = FetchType.EAGER)
  (name = "customer_id")
  private Customer customer;
  ...
}

LazyInitializationException: could not initialize proxy – no Session

Almost every Hibernate/JPA noobie struggle with this exception when they started learning (including myself). This is basically saying you’re tring to access unfetched data after transaction has been closed.

If you use Spring declarative transaction management, transaction start and finish mark are declared by simply annotating DAO method with . Let’s see a common failure where LazyInitializationException can happen.

Here’s your CustomerDAO class:


public class CustomerDAO {
  
  ext private EntityManager em;

  
  public List getAllCustomers() {
    List customers = em.createQuery("select c from Customer", 
      Customer.class).getResultList();
    return customers;
  }

Then on your controller you populate your Model object with list of Customers, and on your view your JSP tried to access Accounts associated with each customer:

Customer Info

Id: ${customer.id} Name: ${customer.name} Accounts:
  • Acc Id: ${acc.id}, Balance: ${acc.balance}

Since the transaction is already closed when CustomerDAO.getAllCustomers() method returns, this will throw LazyInitializationException.

My preferred strategy to overcome this problem is to prefetch the related entities on the DAO, so all the information we need is available on view level in detached state. Other strategy being opening a transaction / session while view is being generated (see: ). To achieve this, change the getAllCustomers() DAO method to use JPQL left join fetch syntax like this:


public class CustomerDAO {
  ...
  
  public List getAllCustomers() {
    List customers = em.createQuery(
      "select distinct c from Customer " +
      "left join fetch c.accounts", 
      Customer.class).getResultList();
    return customers;
  }
  ...
}

Now you can iterate and access all related accounts entities without exceptions.

One thought on “Entity Relationship On Hibernate JPA”

Leave a Reply