1

当尝试放置从我通过休眠从数据库加载的对象中获取的字符串列表时,我遇到了这个异常。

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

我用来加载列表的方法是在事务中。但是当我尝试将列表放入模型中时,我得到了上述异常。我从中得到了休眠要求我在事务中也有这行代码。但是鉴于它不是数据库操作,为什么会这样呢?

@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";
}

服务对象。

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));
}

}

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();
}

}

4

4 回答 4

1

我对 Hibernate 比较陌生,但我会根据我对它的理解来猜测一下。

默认情况下@OneToMany,集合是延迟加载的。因此,当您加载 Person 对象时,将创建一个代理来代替您的实际comments列表。在您按原样调用该列表的吸气剂(即)之前,不会加载该列表getComments(),即使那样我也不认为会立即加载完整列表,更是如此(是的,多个数据库调用)如果您调用 .size(),您将遍历列表或整个列表。

但是,我认为这里的问题是您必须在加载父 ( Person) 对象的同一会话中加载列表。当您加载Person对象时,您有对当前会话的引用,然后一旦您调用该getComments()Person 对象,会话就会关闭。

我认为要将整个过程保持在一个会话中,您可以像在 DAO 类中那样手动打开和关闭会话。

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

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

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

    return comments;
}

将 FetchType 设置为 EAGER 可以解决问题,但根据我的阅读,通常不建议这样做,除非您总是需要使用 Person 对象加载评论。

于 2012-11-23T18:43:22.383 回答
0

将获取类型更改为FetchType.EAGER.

于 2012-11-23T17:52:53.920 回答
0

我认为问题在于您正在使用

currentSession()

尝试将其替换为

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

因为异常表明没有任何打开的会话。

于 2012-11-23T17:56:32.873 回答
0

您应该查看Person类映射,也许该Comments字段与LAZY属性映射,因此它没有加载到 DAO 中。当您调用该getComments方法时,Hibernate 尝试从数据库加载属性,但当时没有会话,因此出现异常。要解决此问题,请将映射属性更改为EAGER.

于 2012-11-23T17:58:53.007 回答