gpt4 book ai didi

java - 使用 hibernate 和 spring 将持久对象的字符串集合加载到模型中

转载 作者:太空宇宙 更新时间:2023-11-04 07:56:34 24 4
gpt4 key购买 nike

当尝试放置从我通过 hibernate 从数据库加载的对象中获取的字符串列表时,我收到此异常。

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

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

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

}

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

}

最佳答案

我对 Hibernate 比较陌生,但我会根据我对它的理解对此进行猜测。

默认情况下,@OneToMany 集合是延迟加载的。因此,当您加载 Person 对象时,将创建一个代理来代替您的实际 comments 列表。直到您按原样调用该列表的 getter(即 getComments())后,该列表才会加载,即使这样,我也不认为会立即加载完整列表,更重要的是,当您迭代列表时,会一一加载(是的,多个数据库调用),或者如果您调用 .size(),则一次加载整个列表。

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

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

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 对象加载注释。

关于java - 使用 hibernate 和 spring 将持久对象的字符串集合加载到模型中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13533623/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com