0

When I try to place a list of stings taken from an object, I've loading in from a database via hibernate, I'm getting this exception.

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

The method I've used to load the list is within a transaction. But when I try to place the list in the model I get the above exception. I'm taking from this that hibernate is requiring me to have even this line of code within a transaction also. But given that it's not a database operation why is this so?

@RequestMapping(value="{id}", method=RequestMethod.POST)
public String addComment(@PathVariable String id, Model model, String comment) {
    personService.addComment(Long.parseLong(id), comment);
    Person person = personService.getPersonById(Long.parseLong(id));
    model.addAttribute(person);
    List<String> comments = personService.getComments(id);
    model.addAttribute(comments);
    return "/Review";
}

Service object.

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


public class PersonServiceImpl implements PersonService {

private Workaround personDAO;


public PersonServiceImpl() {
}

@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void savePerson(Person person) { 
    personDAO.savePerson(person);
}

@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public Person getPersonById(long id) {
    return personDAO.getPersonById(id);
}

@Autowired
public void setPersonDAO(Workaround personDAO) {
    this.personDAO = personDAO;
}

@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public List<Person> getAllPeople() {
    return personDAO.getAllPeople();
}

@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public void addComment(Long id, String comment) {
    Person person = getPersonById(id);
    person.addComment(comment);
    savePerson(person);
}

@Transactional(propagation=Propagation.REQUIRED, readOnly=false)
public List<String> getComments(String id) {
    return personDAO.getComments(Long.parseLong(id));
}

}

DAO

import java.util.List;

import javax.persistence.ElementCollection;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;



@Repository
public class PersonDAO implements Workaround {
private SessionFactory sessionFactory;

@Autowired
public PersonDAO(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;   
}

private Session currentSession() {
    return sessionFactory.getCurrentSession();
}

public void addPerson(Person person) {
    currentSession().save(person);
}

public Person getPersonById(long id) {
    return (Person) currentSession().get(Person.class, id);
}


public void savePerson(Person person) {
    currentSession().save(person);
}

public List<Person> getAllPeople() {
    List<Person> people = currentSession().createQuery("from Person").list();
    return people;
    
}

public List<String> getComments(long id) {
    return getPersonById(id).getComments();
}

}

1
  • Could you please post the spring configuration file where you setup the persistence. I think the problem is in your config, not in the code (because the code looks fine). And please post the Person class and the complete stack trace with some hints about the line numbers. Commented Nov 24, 2012 at 8:41

4 Answers 4

1

I am relatively new to Hibernate but I'll take a guess at this from my understanding of it.

By default @OneToMany collections are lazily loaded. So when you load your Person object a proxy will be created in place of your actual comments list. This list won't be loaded until you call the getter for that list (ie getComments()) as you are, and even then I don't think the full list is loaded at once, more so one by one (yep multiple db calls) as you iterate through the list or the whole list at one if you call .size().

However, I think the catch here is that you must load the list within the same session that you load the parent (Person) object. When you are loading the Person object you have a reference to the current session and then once you call the getComments() on that Person object the session is closed.

I think to keep the whole process in one session you could manually open and close your session like so in your DAO class.

public List<String> getComments(long id) {
    Session session = sessionFactory.openSession();

    List<String> comments = getPersonById(id).getComments();

    sessionFactory.getCurrentSession().flush();
    sessionFactory.getCurrentSession.close();

    return comments;
}

Setting the FetchType to EAGER would solve the problem, but from what I have read it is generally not recommended unless you always need the comments loaded with the Person object.

Sign up to request clarification or add additional context in comments.

2 Comments

This was the right idea. However, there's a Hibernate static method for initializing collections Hibernate.initialize(). I just used this method in my DAO method that gets the collection and now everything's gravy.
Great thanks for posting that, I didn't know about Hibernate.initialize() so that sounds much easier.
0

Change a fetch type to FetchType.EAGER.

Comments

0

I think the problem is that you're using

currentSession()

Try to replace it with

private Session currentSession() {
    return sessionFactory.openSession();
}

bcause the exception says that there isn't any open session.

1 Comment

according to static.springsource.org/spring/docs/3.0.x/… getCurrentSession is right
0

You should review the Person class mapping, maybe the Comments field is mapped with the LAZY attribute and so it's not loaded in the DAO. When you call the getComments method Hibernate tries to load the attribute from the database but at that time there is no session, hence the exception. To solve this issue change the mapping attribute to EAGER.

Comments

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.