jpa – JAXB急切地获取标记为FetchType.LAZY的字段,即使EntityManager已被清除(),关闭()并设置为null

我向apt stackflow社区倾诉并谦卑地寻求指导(我在写这篇文章时屈服于我的头脑)

我有以下Entity类/ bean,它混合了JPA / EclipseLink / JAXB / Moxy注释:( btw Ev​​entBase只是一个包含其他字段的@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的所有成员对象!即客户,客户应用程序以及我为简洁而排除的任何其他映射.我使用EclipseLink作为我的JPA提供程序,使用Moxy作为JAXB.我在这做错了什么?您可以看到,不仅virtualManager和entityManagerFactory实例被清除,关闭并设置为null,而且我还继续分离根事件实体.而且,fetchtype已明确设置为LAZY!

当Event对象被分离时,JAXB如何急切地获取?我认为关闭entityManager本身会分离所有托管对象?是否有一些JAXB挂起的缓存会话上下文?如果是这样,为什么它甚至不尊重明确定义的获取策略?
提前谢谢了!

乌斯塔德阿

最佳答案 如果eclipselink处于独立模式,那么只有ManyToMany和OneToMany关系实际上使用延迟加载,对于其他关系,fetch属性被忽略并等于EAGER.

这是http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Mapping/Basic_Mappings/Lazy_Basics的文档

One-to-one: By default, EclipseLink JPA ignores the fetch attribute and
default javax.persistence.FetchType.EAGER applies.

Many-to-one: EclipseLink JPA performs lazy loading when the fetch
attribute is set to javax.persistence.FetchType.LAZY.

Basic: By default, EclipseLink JPA ignores the fetch attribute and
default javax.persistence.FetchType.EAGER applies.

这就是你的实体加载关系的原因.

希望能帮助到你.

点赞