OpenJPA - ленивая загрузка не работает - PullRequest
0 голосов
/ 28 июля 2011

У меня есть особая проблема с модульным тестом с использованием встроенного контейнера OpenEJB. У меня двунаправленная связь между двумя классами. В одном направлении отношение работает должным образом, но в противоположном направлении оно работает только в режиме EAGER. В режиме LAZY поле section остается пустым. Отрезанный код выглядит следующим образом:

@Entity
@Table(name="tracks")
class TrackEntity implements Track {
    @Id
    private int trackNumber;
    @OneToMany(mappedBy = "track")
    private HashSet<SectionEntity> sections;

    public TrackEntity() {
        sections = new HashSet<SectionEntity>();
    }

    @Override
    public Collection<HistoricalEvent> getEvents() {
        if (sections == null)
            throw new CommonError("number=" + trackNumber, AppErrors.TRACK_EMPTY);

        TreeSet<HistoricalEvent> set = new TreeSet<HistoricalEvent>();
        for (SectionEntity se : sections)
            set.addAll(se.getEvents());

        return set;
    }
 }

Мой код немного специфичен. Класс использует поле sections только для внутреннего объединения всех подколлекций. Я не могу заполнить разделы лениво . Я предполагаю, что контейнер ожидает, что клиент получит доступ к полю извне через геттер.

1 Ответ

2 голосов
/ 08 августа 2011

Это проблема с жизненным циклом.Все объекты (дорожка и ее разделы) должны быть повторно присоединены к контексту постоянства.Метод, собирающий события, должен быть в классе, используя EntityManager.(Сущность не может использовать менеджера для повторного присоединения.) Ниже приведен пример обновленного управляющего класса сущности:

public class EntityDataAccessor {
    @PersistenceUnit(unitName = "someUnit")
    private EntityManagerFactory emFactory;

    //gets one track
    public Track getTrack(int number) {
        EntityManager em = emFactory.createEntityManager();
        try {
            return (Track)em.find(TrackEntity.class, number);
        }
        finally {
            em.close();
        }
    }

    //the new method collecting events
    public Collection<HistoricalEvent> getEventsForTrack(TrackEntity te) {
        EntityManager em = emFactory.createEntityManager();
        te = em.merge(te); //re-attach to the context

        Set<SectionEntity> sections = te.getSections();
        TreeSet<HistoricalEvent> set = new TreeSet<HistoricalEvent>();
        for (SectionEntity se : sections) {
            se = em.merge(se); //re-attach to the context
            set.addAll(se.getEvents());
        }
        em.close();
        return set;
    }
}

См. Вопрос Что такое ленивая стратегия и как она работает? для более подробной информации.

...