我刚刚开始了解 FetchType Lazy 和 Eager。我理解其中的区别,但即使我设置为“惰性”,它仍然试图获取关联的数据。
关系:1 人:多部电话
查看的研究尝试和教程:
https://www.mkyong.com/hibernate/hibernate-one-to-many-relationship-example-annotation/ http://howtodoinjava.com/hibernate/lazy-loading-in-hibernate/ https://howtoprogramwithjava.com/hibernate-eager-vs-lazy-fetch-type/
我知道要获取关联数据,我需要在 session() 中执行此操作,因此对于我的特定示例,在我的 Dao 中,我需要这样的东西
List<Person> persons = criteria.list();
for(Person person : persons){
Set sets = person.getPhones();
}
return persons;
到目前为止正确吗?
但问题是我没有在 Dao、 Controller 等任何地方调用 person.getPhones(),但我得到了 LazyInitializationEception。我似乎无法发现问题出在哪里。
堆栈跟踪
Jun 19, 2017 2:24:01 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [app-dispatcher] in context with path
[/uni-starter-onetomany] threw exception [Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.person.Person.phones, could not initialize proxy - no Session] with root cause
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.app.person.Person.phones, could not initialize proxy - no Session
Person.class
@Entity
@Table(name="person")
@Component
public class Person {
@Id
@GeneratedValue
private int person_id;
private String name;
private String age;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "person")
private Set<Phone> phones;
// Getter and setters
// ToString method by field name not by method
电话.class
@Entity
@Table(name="phone")
@Component
public class Phone {
@Id
@GeneratedValue
private int phone_id;
private String type;
private String phone;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="person_person_id")
private Person person;
// Getter and setters
PersonDao
@Repository
@Transactional
@Component("personDao")
public class PersonDao {
@Autowired
private SessionFactory sessionFactory;
public Session session(){
return sessionFactory.getCurrentSession();
}
public List<Person> getPersonList(){
Criteria criteria = session().createCriteria(Person.class);
List<Person> persons = criteria.list();
// for(Person person : persons){
//
// Set sets = person.getPhones();
//
// }
return persons;
}
public void saveOrUpdate(Person person){
session().saveOrUpdate(person);
}
}
Controller
// Get list
@RequestMapping(path="/list", method = RequestMethod.GET, produces="application/json")
@ResponseBody
public Map<String, Object> getListPerson(){
Map<String, Object> data = new HashMap<String, Object>();
List<Person> persons = personDao.getPersonList();
data.put("results", persons);
System.out.println(persons);
return data;
}
问题
只要我不在 session 中调用 person.getPhones(),它就应该只返回 person?如果是这样,我收到 LazyInitializationException 的问题可能是什么?
我还看到有人在 Dao 类中 setFetchMode() FetchMode.JOIN 例如 Hibernate Criteria Join with 3 Tables 也许这可能是主观的,但更好的做法是什么?有任何性能问题吗?
非常感谢任何想法、链接或文章...
更新 感谢 Abassa 从 Person.class 的 toString 中删除 Phone 解决了这个问题。但我刚刚意识到,由于 Jackson,在序列化过程中它会尝试获取 Phone 对象......有解决方法吗?
Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: failed to lazily initialize a collection of role: com.app.person.Person.phones, could not initialize proxy - no Session
最佳答案
从 Person 类的 toString 方法中删除电话字段。
当您调用时:
System.out.println(persons);
您尝试访问电话字段,因为 println 为列表中的每个人调用 toString 方法,因此您会收到 LazyInitializationException。
关于java - Spring Hibernate FetchType LazyInitializationException 即使不调用关联时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44628547/