ORMLite 和惰性集合的问题

发布于 2024-12-02 05:36:57 字数 1162 浏览 2 评论 0原文

我在我的 android 项目中使用 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 对象,例如 在示例中

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

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

尝试获取所有 userShows 时:

shows = userShowsDao().queryForAll();

UserShow 对象有一个外部惰性集合剧集,但是当我 获取包含剧集集合的所有节目对象。为什么会出现这种情况?集合是惰性的,我必须获取 null 或其他内容,但没有 Episode 对象的集合。如何让这个集合真正变得懒惰?如果 ORMLite 能够在没有延迟集合的情况下获取对象并在真正需要时进行初始化,那可能会很酷。例如作为 Hibernate.initialize 方法。

谢谢!

I am using ormlite in my android project. I have two classes

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

I am saving my UserShows objects like in example

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

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

UserShow object have a foreign lazy collection episodes, but when I am trying to get all userShows:

shows = userShowsDao().queryForAll();

I am getting all shows objects with collections of episodes. Why this happens? Collection is lazy and I must to get null or something else but no collection of Episode object. How to make this collection really lazy? It may be cool if ORMLite have ability get objects without lazy collections and initialize when it really need. For example as Hibernate.initialize method.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迷爱 2024-12-09 05:36:57

惰性集合已经过良好的测试,并且被许多其他人使用,因此尽管它可能存在错误,但您更有可能被惰性集合类欺骗。

从 DAO 检索每个 UserShow 对象时,episodes 不会为 null,而是使用 LazyForeignCollection 实例进行设置。但是,不会进行任何其他查询,并且集合中不会包含Episode 数据。如果您随后调用集合上的方法之一,例如 userShow.getEpisodes().iterator(),那么此时将进行一个单独查询允许您迭代该节目的剧集。这就是惰性集合的工作原理。

如果您仍然认为惰性集合不起作用,请向我们展示您如何确定节目具有剧集数据。要查看在何处执行哪些查询,您可以使用 ORMLite 启用 Android 日志记录


编辑:

事实证明,@Georgy 正在使用调试器来调查该集合。调试器很可能调用相同的 iterator()toArray() 方法,从而导致在该时刻发出集合查询。因此,在调试器请求之前,集合中没有任何剧集。

The lazy collections have been well tested and are in use by many others so although there could be bugs with it, it is more likely that you are being tricked by the lazy collection class.

When each of the UserShow objects is retrieved from the DAO, the episodes will not be null but instead will be set with an instance of LazyForeignCollection. However, no additional queries will be made and there will be no Episode data contained by the collection. If you then make a call to one of the methods on the collection such as userShow.getEpisodes().iterator(), then a separate query is made at that time to allow you to iterate through that show's episodes. That's how the lazy collections work.

If you still think that the lazy collections aren't working then please show us how you are determining that the shows have episode data. To see what queries are being done where, you can enable Android logging with ORMLite.


Edit:

It turns out that @Georgy was using the debugger to investigate the collection. The debugger is most likely calling the same iterator() or toArray() methods which cause the collection queries to be issued at that instant. So there weren't any episodes in the collection before the debugger asked for them.

一梦等七年七年为一梦 2024-12-09 05:36:57

你的例子应该没​​问题。我创建了相关的测试表并插入了 2 个usershows 和 3 个episodes。然后我跟踪 MySQL 日志(通过使用 --general-log= 运行 MySQL 来设置 - 请参阅 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 }

日志仅显示运行的一个选择语句:

110830 13:11:09     1 Query SELECT * FROM `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

Your example should be OK. I created the relevant test tables and inserted 2 usershows and 3 episodes. I then tailed the MySQL log (set by running MySQL with --general-log=<log file name> - see http://dev.mysql.com/doc/refman/5.5/en/query-log.html).

Full test Groovy script:

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 }

Log shows only one select statement ran:

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

Change the last line to the following (which iterates over all usershows and gets the episodes field for each one:

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

Results in:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文