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()ません。それでも、完全なリストが一度にロードされるとは思わないので、1つずつ(複数のdb呼び出し) .size()を呼び出す場合は、リストまたはリスト全体を1つずつ繰り返し処理します。

Personただし、ここでの落とし穴は、親( )オブジェクトをロードするのと同じセッション内でリストをロードする必要があることだと思います。オブジェクトをロードするときは、現在のセッションへの参照があり、そのPersonオブジェクトPersonを呼び出すと、セッションが閉じられます。getComments()

プロセス全体を1つのセッションに保持するために、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 に答える