2011-08-30 92 views
4

我在我的android項目中使用ormlite。我有兩個類ORMLite和懶惰集合的問題

@DatabaseTable(tableName = "usershows") 
public class UserShow { 
    @DatabaseField(id = true) 
    private Integer showId; 

    @ForeignCollectionField(eager = false) 
    private ForeignCollection<Episode> episodes; 
    ... 
} 

@DatabaseTable(tableName = "episodes") 
public class Episode { 
    @DatabaseField(id = true) 
    private Integer episodeId; 

    @DatabaseField(foreign = true) 
    private UserShow show; 
    ... 
} 

我救了我的UserShows對象,如in example

UserShow show = new UserShow(); 
userShowDao.create(show); 

for (Episode e: eps) { 
    e.setShow(show); 
    episodeDao.create(e); 
} 

usershow將對象有個外國延遲集合的情節,但是當我試圖讓所有userShows:

shows = userShowsDao().queryForAll(); 

我正在收集所有節目集合的劇集。爲什麼會發生?集合是懶惰的,我必須得到空或其他東西,但沒有收集Episode對象。如何讓這個收藏真的很懶?如果ORMLite能夠在沒有延遲集合的情況下獲取對象,並在真正需要時進行初始化,那可能會很酷。例如Hibernate.initialize方法。

謝謝!

回答

4

懶惰的集合已經過很好的測試,並且被許多其他用戶使用,所以雖然可能會有bug,但它更可能被懶惰的集合類欺騙。

當從DAO中檢索到每個UserShow對象時,episodes將不會爲空,而會設置爲LazyForeignCollection的實例。但是,不會進行額外的查詢,並且該集合中不會包含任何Episode數據。如果您隨後撥打集合中的其中一種方法(例如userShow.getEpisodes().iterator()),則可以單獨使用查詢,以便您可以遍歷該節目的劇集。這就是懶惰集合的工作原理。

如果你仍然認爲懶惰的收藏不起作用,那麼請告訴我們你是如何確定節目有插曲數據。要查看正在進行哪些查詢,可以啓用Android logging with ORMLite


編輯:

事實證明,@Georgy使用調試器來調查收集。調試器很可能調用相同的iterator()toArray()方法,這會導致在該時刻發出收集查詢。所以在調試器詢問它們之前,集合中沒有任何情節。

+0

灰色,謝謝你的回覆。我正在獲取具有已初始化劇集集合的userShows對象,但是我不會對劇集進行任何調用。 –

+0

我可以在我的調試器中看到這個http://postimage.org/image/cdqihamc/方法 public List getAllUserShows(){ List shows = null; try { shows = getHelper()。getUserShowsDao()。queryForAll(); catch(SQLException e){ e.printStackTrace(); } return shows; } –

+0

是的,你的調試器正在調用'iterator()'和其他方法,使查詢在那一點。它顯示那裏有劇集,但在調試器要求他們之前,他們不會在那裏。如果打開日誌記錄功能,只有當調試器顯示有關集合的信息時,才能看到正在查詢的查詢。 – Gray

1

你的例子應該沒​​問題。我創建了相關的測試表並插入了2個usershows和3個episodes。然後,我跟蹤MySQL日誌(通過運行MySQL設置--general-log=<log file name> - 請參閱http://dev.mysql.com/doc/refman/5.5/en/query-log.html)。

全面測試Groovy腳本:

import com.j256.ormlite.dao.DaoManager 
import com.j256.ormlite.jdbc.JdbcConnectionSource 
cs = new JdbcConnectionSource('jdbc:mysql://localhost/episode?user=root') 
epDao = DaoManager.createDao(cs,Episode) 
usDao = DaoManager.createDao(cs,UserShow) 
usDao.queryForAll().each { println it } 

日誌顯示只有一個select語句跑:

110830 13:11:09  1 Query SELECT * FROM `usershows` 

更改的最後一行以下(其中遍歷所有usershows並得到情節領域每個:

usDao.queryForAll().each { println it.episodes } 

結果於:

110830 13:15:31  1 Query SELECT * FROM `usershows` 
        1 Query SELECT * FROM `episodes` WHERE `show_id` = 1 
        1 Query SELECT * FROM `episodes` WHERE `show_id` = 2 
+0

不知道,謝謝你的回覆。正如我在你的例子中看到的那樣,劇集可以按需提供。但在我的項目中,當我得到usetShows對象並且沒有任何對情節的調用時,無論如何,我也會得到情節。我可以在debbuger中看到這個。如何在沒有劇集的情況下獲得usershows? –

+2

我想象調試器強制檢索劇集?也就是說,由於ForeignCollection接口是java.util.Collection和Iterable,調試器知道如何查看內容;一旦它發生,它就會觸發從數據庫中檢索的事件。 – Unk

+0

這是非常奇怪的行爲,如果這是真的。由於hibernate的行爲是不同的,debbuger明確表示集合是懶惰的,無法獲得它的強制。 –