4

私は apt stackoverflow コミュニティに頭を下げ、謙虚に指導を求めます (これを書いているときは従順で頭を下げます)

JPA/EclipseLink/JAXB/Moxy アノテーションが混在する次のエンティティ クラス/Bean があります: (ところで、EventBase は、追加のフィールドを保持する単なる @MappedSuperclass です)

@Entity
@Table(name = "EVENTS")
@XmlRootElement
public class Event extends EventBase {
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @XmlAttribute(name = "id")
    private long eventCID;

    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "APPLICATIONCID")
    private CustomerApplication customerApplication;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "CUSTOMERCID")
    private Customer customer;

    ....
}

このエンティティをマーシャリングするための私のコードは次のとおりです(簡潔にするために外部クラスは除外されています)

public static void main(String args[]) {
    Event event = myInstance.populateEvent();
    myInstance.buildXMLFromEvent(event);
}

public Event populateEvent() {

    EntityManagerFactory emf = Persistence.createEntityManagerFactory(this.persistenceUnit);
    EntityManager em = null;

    Event event = null;
    try {
        em = emf.createEntityManager();
        event = (Event) em.createQuery("Select object(e) from Event e where e.eventCID = 55000").getSingleResult();
        em.clear();
        em.detach(event);
        em.close();
        em = null;
        emf.close();
        emf = null;
    } catch (Exception e) { // just test code so catching general exception
        log.error("Unexpected error: " + e);
    } finally {
        if (em != null) {
            em.clear();
            em.close();
        }
    }
    return event;
}

private void buildXMLFromEvent(Event event) {

    System.out.println("Marshalling now:");
    JAXBContext jc;
    try {
        jc = JAXBContext.newInstance(Event.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.valueOf(true));
        JAXBElement<Event> jaxbElement = new JAXBElement<Event>(new QName("event"), Event.class, event);
        marshaller.marshal(jaxbElement, System.out);
    } catch (JAXBException e) {
    }
}

生成された xml は実際に実行され、Event エンティティ Bean のすべてのメンバー オブジェクトを積極的に取得します。つまり、Customer、CustomerApplication、および簡潔にするために除外したその他のマッピング。JPAプロバイダーとしてEclipseLinkを使用し、JAXBにはMoxyを使用しています。ここで何が間違っていますか?entityManager および entityManagerFactory インスタンスがクリアされ、閉じられ、null に設定されているだけでなく、先に進んでルート Event エンティティも切り離されていることがわかります。さらに、fetchtype は明示的に LAZY に設定されています。

Event オブジェクトが切り離されているのに、JAXB が熱心に取得できるのはなぜですか? entityManager 自体を閉じると、すべての管理対象オブジェクトが切り離されると思いましたか? JAXB が保持しているキャッシュされたセッション コンテキストはありますか? もしそうなら、明示的に定義されたフェッチ戦略を尊重していないのはなぜですか? よろしくお願いします!

ウスタッド

4

1 に答える 1

2

eclipselinkがスタンドアロンモードの場合、ManyToManyとOneToManyの関係のみが実際に遅延読み込みを使用します。他の場合、フェッチ属性は無視され、EAGERと等しくなります。

これがそのhttp://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Basic_Mappings/Lazy_Basicsのドキュメントです。

1対1:デフォルトでは、EclipseLink JPAはフェッチ属性を無視し、デフォルトのjavax.persistence.FetchType.EAGERが適用されます。

多対1:フェッチ属性がjavax.persistence.FetchType.LAZYに設定されている場合、EclipseLinkJPAは遅延読み込みを実行します。

基本:デフォルトでは、EclipseLink JPAはフェッチ属性を無視し、デフォルトのjavax.persistence.FetchType.EAGERが適用されます。

そのため、エンティティにはリレーションがロードされます。

それが役に立てば幸い。

于 2012-08-26T18:09:23.130 に答える