2011-08-30 61 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明确表示集合是懒惰的,无法获得它的强制。 –