2017-06-19 46 views
0

我剛開始瞭解FetchType Lazy和Eager。我瞭解其中的差異,但即使我設置爲Lazy,它仍以嘗試獲取相關數據。Spring Hibernate FetchType LazyInitializationException即使未調用關聯

關係: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; 

到目前爲止是否正確?

但問題是我沒有調用person.getPhones()任何地方不在Dao,controller..etc但我得到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 

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

}

控制器

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

問題

  1. 只要我不叫會話應該會在person.getPhones()只返回人?如果是這樣,那麼我可能會遇到LazyInitializationException?

  2. 我還看到有人調用setFetchMode()FetchMode.JOIN在例如 Hibernate Criteria Join with 3 Tables 也許這可能是主觀的,但什麼DAO類將是一個更好的做法?任何性能問題?

任何想法,鏈接或文章大加讚賞...

UPDATE 由於Abassa從的toString Person.class中移除電話解決了這個問題。但我只是意識到,由於傑克遜,在序列化期間,它試圖獲取Phone ojbect ....是否有解決方法?

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 
+0

你是否在Person類的toString方法中打印手機屬性? –

+0

當您需要指定如何獲取關係時,Fetchmode非常有用。 通過加入或選擇FecthMode。 請參閱文檔:https://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/FetchMode.html 根據您的數據庫模型,選擇其中一個可能會導致性能問題。 –

+0

@AbassA是的,我必須親自試試 –

回答

1

從Person類的toString方法刪除手機領域。

當你撥打:

System.out.println(persons); 

您嘗試訪問手機領域,因爲的println要求每個人在列表中toString方法讓您得到LazyInitializationException中。

相關問題