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 Setaccounts; // 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 Setaccounts; // 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 Setaccounts; ... }
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 ListgetAllCustomers() { 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 ListgetAllCustomers() { 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.
Hi
Can you please help me in
http://stackoverflow.com/questions/18895585/hibernate-version-annotation-and-object-references-an-unsaved-transient-instanc