1

I am getting this exception nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.ibm.ro.model.Location.subLocations, could not initialize proxy - no Session.

I do get that upon accessing the collection, the transaction has already been closed that's why the code is throwing this exception. Here is my sample code

@Entity
@Table(name="location")
public class Location extends BaseEntity {

    private static final long serialVersionUID = 1L;

    private String name;
    private List<Location> subLocations;
    private Location location;

    @Column(name="name")
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "location")
    public List<Location> getSubLocations() {
        return subLocations;
    }
    public void setSubLocations(List<Location> subLocations) {
        this.subLocations = subLocations;
    }

    @ManyToOne(fetch = FetchType.LAZY)
    public Location getLocation() {
        return location;
    }
    public void setLocation(Location location) {
        this.location = location;
    }

    @Override
    public String toString() {
        return "Location [name=" + name + ", subLocations=" + subLocations
            + "]";
    }

}

Here is my DAO:

@Repository("locationDao")
public class LocationDao implements ILocationDao{

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    public List<Location> getAll() {
        Session sess = getSession();
        return sess.createCriteria(Location.class).setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY).list();
    }
}

Then here is my service :

@Service("locationService")
@Transactional
public class LocationService implements ILocationService{

    @Autowired
    ILocationDao dao;

    @Override
    public List<Location> getAll() {
        return dao.getAll();
    }
}

Here is the controller where the exception is being thrown:

@Controller
public class BaseController {

    @Autowired
    ILocationService service;

    private static final String VIEW_INDEX = "index";
    private final static org.slf4j.Logger logger =    LoggerFactory.getLogger(BaseController.class);

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String location(ModelMap model) {        
    logger.debug(service.getAll().toString());
        return VIEW_INDEX;
    }
}

What can I do to fix the problem without using OpenSessionInViewFilter?

1
  • You can fetch them eagerly by changing in entity Commented Mar 6, 2015 at 10:23

1 Answer 1

1

You can iterate your Location inside your service (where you still have your transaction) and call Hibernate.initialize on the elements, the force initialization of a persistent collection.

    @Override
    public List<Location> getAll() {
        List<Location> locations = dao.getAll();
        for (Location location : locations ) { 
          Hibernate.intialize(location.getSubLocations())
        }
        return locations;
    }
Sign up to request clarification or add additional context in comments.

6 Comments

He has @Transactional, he does not need to call Hibernate.intialize explicitly, calling location.getSubLocations() in his service would be enough, and sub locations will be initialized.
true, though he would have to call location.getSubLocations().size() or any other method. But Hibernate.initialize is a dedicated method that lets you avoid just that. It explicitly marks the purpose of initializing only. Otherwise if it were to be JPA, I would resort to what you mentioned, but I understand that OP is using Hibernate directly, and in that case I would use Hibernate.initialize instead, its my rule of thumb
I understand that this is a best practice from HIbernate. However making services depending on ORM is not a good idea imho. What if tomorrow you change your mind and stop using hibernate? So better to keep it as clean as possible, and do not depend on ORM specific methods.
yes, though this consideration needs to be set on a higher level, so choosing JPA/Hibernate over Hibernate directly. If you look at the code snippets as posted, you'll see a few more changes that would need to be changed if hibernate is swapped out. So personally, if its hibernate only, I would initialize using a dedicated Hibernate.initialize only, on the other hand, personally I always strive developing against JPA interfaces. Good remarks, maybe you'll spurr a more conceptual redesign with the OP
Hi Master Slave, I tried using your answer and it worked perfectly on getAll(). but oddly, I have another method getRegions() that still throws the lazyinitializationexception. I copied and paste the same block of code, changing only getAll() to getRegions(). Any ideas why is that? Thanks in advance.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.