LazyInitializationException with OneToMany in the simpliest way
I'm using Hibernate with jpa and I'm getting LazyInizializationException trying to do a very simple thing. I know what does LazyInizializationException means but I can't understand why it comes while i'm doing everything in the most common and simple way. This is the "one" side of the relationship:
@Entity
public class User implements Serializable{
@Id @Generated开发者_运维问答Value
private int idUser;
private String name;
private String surname;
private String username;
@OneToMany(mappedBy="user")
private List<Device> dev;
...getters and setters...
and this is the "Many" side:
@Entity
public class Device implements Serializable {
@Id @GeneratedValue
private int idDevice;
private String brand;
private String model;
@ManyToOne
@JoinColumn(name="user_fk")
private User user;
...getters and setters...
the jUnit test that throws the exception is:
@Test
public void testLazyUserSnd() {
User u = uDao.getUser(2);
List<Device> devList = u.getDev();
Device aDevice = devList.get(0); // <--- Here the exception is thrown
aDevice.getModel();
I made the relationship as explained in the Hibernate Documentation. Any hint? Am I making some big and stupid mistakes?
While @Xavi's answer is perfectly reasonable, you may not always want to load the devices for a user. If you don't, there are 2 ways of fixing this.
- Create an additional method uDao.getUserWithDevices(id) and call that when you know you need devices, otherwise call the uDao.getUser(id).
- Encapsulate the test method, and therefore any production code that uses the method, in a transaction. In other words keep the session open as long as you need to.
Personally I'd use the transaction method since as it allows more flexibility and allows JPA to lazy load whenever it needs to. See also http://community.jboss.org/wiki/OpenSessionInView for more interesting information around session lifecycle.
The exception is telling you that you're trying to get some of the lazy-loaded association's elements when the session is closed. Probably you should call u.getDev()
or Hibernate.initialize(u.getDev())
inside the dao's method, when the hibernate session is still open.
Or, if you're using Criteria
, you could also use setFetchMode
to force eager fetching.
public User getUser(String id) {
Session session = getSession();
Criteria criteriaQuery = session.createCriteria(User.class);
criteriaQuery.add(Expression.eq("id", id));
criteriaQuery.setFetchMode("dev", FetchMode.JOIN);
return criteriaQuery.uniqueResult();
}
The entity is probably detached from the session (transaction context) when you access the relation. Try to enclose your test method in a transaction.
精彩评论