1

I get the an exception when trying to get data, lazily(Exception at the very end)

//application gets data by the following DAO.

    public T findById(PK id) {
    T result = getHibernateTemplate().get(this.type, id);
    getHibernateTemplate().flush();
    return result;
}  

//Junit test calls a serviceX.getById

    @Transactional
    public SomeObject getById(int x){
         return (SomeObject) aboveDao.findById(x);         

    }

//Withing the JUnit

 SomeObject someObj = serviceX.getById(3);
 someObj.getAnotherObject().y.equals("3"); //**Exception** at this line.

//SomeObject class has the following property.

 @OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)  
 private AnotherObject anotherObject;

I get the following exception when tryin to access anotherObject in the junit

Methods already tried + extra configuration

We use spring annotation TransactionManager. <tx:annotation-driven /> specified in the config file.

Also, I tried to add @Transaction(propagation = Propagation.REQUIRED) on top of the JUnit, this did not solve the issue. If I run the application, it works without any issues.

How to solve this type of issue for JUnit?

 org.hibernate.LazyInitializationException: failed to lazily initialize 
 a collection of role xxxxx , no session or session was closed
Zeus
  • 5,885
  • 5
  • 44
  • 79

2 Answers2

2

Here's what happens

SomeObject someObj = serviceX.getById(3); // @Transactional boundary, no more session
someObj.getAnotherObject().y.equals("3"); // session doesn't exist, can't fetch LAZY loaded object

Because your AnotherObject is LAZY fetched, it doesn't actually get loaded in the getById() method. The Session it was associated with is lost when the @Transactional ends, ie. when execution returns from getById(). Because there is no longer a Session, you get the exception.

You can change your FetchType to EAGER. If you're going to that field of your object, you need to initialize it in your Transaction boundaries.

If you only some times need the anotherObject, a possible solution is to create a @Transactional method that calls the getById and eagerly loads the object.

@Transactional
public SomeObject eagerGetById(int x){
    SomeObject obj = getById(x);
    obj.getAnotherObject(); // will force loading the object
    return obj;
}

Calls this method whenever you need to eagerly load the object.

Sotirios Delimanolis
  • 252,278
  • 54
  • 635
  • 683
  • I've tried to remove the @Transactional on top of the service method. Still the JUnit throws an exception as it cannot load the anotherObject. Is there a work around? If you look at the DAO, we use HibernateTemplate, does it open and close the session? is this causing the object to not load the data? – Zeus Oct 01 '13 at 18:09
  • @Zeus Who told you to remove the `@Transactional`? I suggested you change from `FetchType.LAZY` to `FetchType.EAGER`. – Sotirios Delimanolis Oct 01 '13 at 18:09
  • I cannot change the fetch type from Lazy to Eager, as we do not need this data always and the amount of data that is brought down is several thousands every time. – Zeus Oct 01 '13 at 18:14
  • Looks like the obj.getAnotherObject() also fails to get it, it does not throw error this time, it just fails to query the result. any pointers on this ? – Zeus Oct 01 '13 at 20:32
  • @Zeus What do you mean _it fails to query the result_? What happens when you call `someObj.getAnotherObject().y.equals("3");`? – Sotirios Delimanolis Oct 01 '13 at 20:34
  • Actually, it does nothing, when I call this method someObj.getAnotherObject() has PersistantSet assigned to it after I go past this line when debugging. When I try to inspect whats in it, it queries the DB at that point of time. – Zeus Oct 01 '13 at 20:44
  • http://stackoverflow.com/questions/14542140/hibernate-org-hibernate-lazyinitializationexception-could-not-initialize-proxy This solution worked for me later, its weird that I have to pull the data using Hibernate.initialize(prox); Thanks Sotirios for helping. – Zeus Oct 01 '13 at 20:53
  • @Zeus I believe `obj.getAnotherObject();` or maybe calling a member method on it like `obj.getAnotherObject().someMethod()` actually does the same thing `Hibernate.initialize` does. – Sotirios Delimanolis Oct 01 '13 at 20:58
0

This is could be useful to you LazyInitilializationException

John Alexander Betts
  • 3,560
  • 6
  • 39
  • 65
  • My question is completely different than the one that is mentioned in the article. Also, We use the annotations currently in the application for lazy and eager. I'm right now struggling with transaction boundaries. – Zeus Oct 01 '13 at 18:17