开发者

OpenJPA - lazy fetching does not work

开发者 https://www.devze.com 2023-03-23 20:32 出处:网络
I have a specific problem with an unit test using embedded OpenEJB container. I have a bi-directional relation between two classes. In one direction the relation works properly, but in the opposite di

I have a specific problem with an unit test using embedded OpenEJB container. I have a bi-directional relation between two classes. In one direction the relation works properly, but in the opposite direction the relation works only in EAGER-mode. In LAZY-mode the field section stays null. The code snipped follows:

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

My code is little bit specific. The class uses the field sections just internally to merge all sub-collections. I'm unable to fill sections lazily. 开发者_运维技巧I thing, the container expects client to access the field externally via a getter.


Its the problem with life cycle of enties. All enties (track and its sections) must be re-attached to the persistence context. The method collecting events must be in the class using EntityManager. (The entity cannot use the manager to re-attach itself.) Example of updated entity managing class follows:

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

See question What's the lazy strategy and how does it work? for more detail.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号