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!
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.
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