Проблемы с ORMLite и ленивыми коллекциями

Я использую ormlite в моем проекте Android. У меня два класса

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

У объекта UserShow есть иностранные ленивые эпизоды коллекции, но когда я пытаюсь получить все userShows:

shows = userShowsDao().queryForAll();

Я получаю все объекты шоу с коллекциями эпизодов. Почему это происходит? Коллекция ленива, и я должен получить null или что-то еще, но не коллекцию объекта Episode. Как сделать эту коллекцию действительно ленивой? Было бы здорово, если бы ORMLite имел возможность получать объекты без ленивых коллекций и инициализировать, когда это действительно необходимо. Например как Hibernate.initialize метод.

Спасибо!

2 ответа

Решение

Ленивые коллекции были хорошо протестированы и используются многими другими, поэтому, хотя в них могут быть ошибки, более вероятно, что вас обманывает класс ленивых коллекций.

Когда каждый из UserShow объекты извлекаются из DAO, episodes не будет нулевым, но вместо этого будет установлен с экземпляром LazyForeignCollection, Однако никаких дополнительных запросов не будет и не будет Episode данные, содержащиеся в коллекции. Если вы затем сделаете вызов одного из методов в коллекции, таких как userShow.getEpisodes().iterator()Затем выполняется отдельный запрос, чтобы вы могли перебирать эпизоды этого шоу. Вот как работают ленивые коллекции.

Если вы все еще думаете, что ленивые коллекции не работают, пожалуйста, покажите нам, как вы определяете, что шоу имеют данные эпизодов. Чтобы увидеть, какие запросы где выполняются, вы можете включить ведение журнала Android с ORMLite.


Редактировать:

Оказывается, @Georgy использовал отладчик для исследования коллекции. Отладчик, скорее всего, вызывает тот же iterator() или же toArray() методы, которые заставляют запросы коллекции быть выпущенными в тот момент. Так что в коллекции не было никаких эпизодов, пока их не попросил отладчик.

Ваш пример должен быть в порядке. Я создал соответствующие тестовые таблицы и вставил 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 }

Журнал показывает только одну команду выбора:

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
Другие вопросы по тегам