Jpa JAXB急切地获取标记为FetchType.LAZY的字段,即使EntityManager已被清除()、关闭()并设置为null
我向社区鞠躬,谦卑地寻求指导(我写这篇文章时低头屈从) 我有以下实体类/bean,它混合了JPA/EclipseLink/JAXB/Moxy注释:(顺便说一句,EventBase只是一个@MappedSuperclass,它包含额外的字段) 下面是我封送此实体的代码(为了简洁起见,排除了外部类)Jpa JAXB急切地获取标记为FetchType.LAZY的字段,即使EntityManager已被清除()、关闭()并设置为null,jpa,jaxb,lazy-loading,eclipselink,moxy,Jpa,Jaxb,Lazy Loading,Eclipselink,Moxy,我向社区鞠躬,谦卑地寻求指导(我写这篇文章时低头屈从) 我有以下实体类/bean,它混合了JPA/EclipseLink/JAXB/Moxy注释:(顺便说一句,EventBase只是一个@MappedSuperclass,它包含额外的字段) 下面是我封送此实体的代码(为了简洁起见,排除了外部类) publicstaticvoidmain(字符串参数[]){ Event=myInstance.populateEvent(); myInstance.buildXMLFromEvent(事件); }
publicstaticvoidmain(字符串参数[]){
Event=myInstance.populateEvent();
myInstance.buildXMLFromEvent(事件);
}
公共事件populateEvent(){
EntityManagerFactory emf=Persistence.createEntityManagerFactory(this.persistenceUnit);
EntityManager em=null;
事件=null;
试一试{
em=emf.createEntityManager();
event=(event)em.createQuery(“从事件e中选择对象(e),其中e.eventCID=55000”).getSingleResult();
em.clear();
em.detach(事件);
em.close();
em=null;
emf.close();
emf=null;
}catch(异常e){//只需测试代码即可捕获一般异常
日志错误(“意外错误:+e”);
}最后{
如果(em!=null){
em.clear();
em.close();
}
}
返回事件;
}
私有void buildXMLFromEvent(事件事件){
System.out.println(“现在编组:”;
jaxbcontextjc;
试一试{
jc=JAXBContext.newInstance(Event.class);
Marshaller=jc.createMarshaller();
setProperty(marshaller.JAXB_格式化的_输出,Boolean.valueOf(true));
JAXBElement-JAXBElement=new-JAXBElement(新的QName(“事件”),event.class,event);
marshaller.marshall(jaxbElement,System.out);
}捕获(JAXBEException e){
}
}
生成的xml实际上会自动获取我的事件实体bean的所有成员对象!i、 e)客户、CustomerApplication和我为简洁起见排除的任何其他映射。我正在使用EclipseLink作为我的JPA提供者和Moxy for JAXB。我做错了什么?您可以看到,不仅entityManager和entityManagerFactory实例被清除、关闭并设置为null,而且我还进一步分离了根事件实体。此外,fetchtype已显式设置为LAZY
当事件对象被分离时,JAXB如何能够急切地获取呢?我以为关闭entityManager本身会分离所有托管对象?是否存在JAXB挂起的缓存会话上下文?如果是这样,为什么它甚至不遵守显式定义的获取策略?
非常感谢
Ustad如果eclipselink处于独立模式,那么实际上只有ManyToMany和OneToMany关系使用延迟加载,因为其他关系的fetch属性被忽略并等于EAGER 这里有相关的文档 一对一:默认情况下,EclipseLink JPA忽略fetch属性并 默认javax.persistence.FetchType.EAGER适用 多对一:EclipseLink JPA在获取时执行延迟加载 属性设置为javax.persistence.FetchType.LAZY 基本:默认情况下,EclipseLink JPA忽略fetch属性和 默认javax.persistence.FetchType.EAGER适用 这就是为什么你的实体中充满了关系
希望有帮助。好的,似乎在类级别添加@XmlAccessorType(XmlAccessType.FIELD)注释已经阻止了提取这些成员对象。对于如何仍然使用关闭/清除/空entityManager获取对象,我仍然感到困惑。。除非我错过了什么——我很可能错过了!这不是一个很好的实践来直接暴露你的实体,以改进你的设计,你可以考虑创建DTO对象,并通过你自己的阿列克谢来控制视图,谢谢你的评论。这个例子并不一定反映我的设计,我创建这个例子是为了说明……您使用的是哪种ORM实现?@Alexey:我使用EclipseLink作为我的JPA提供者,Moxy for JAXBthanks作为您的研究和帮助!那个参考文档非常有用!无论我有什么样的关系,获取策略总是很急切。请查看我在发布问题后的第一条评论。。我将再次粘贴到这里:“好吧,似乎在类级别添加@XmlAccessorType(XmlAccessType.FIELD)注释现在已经阻止了这些成员对象的获取。我仍然很困惑,如何仍然可以使用闭合/清除/空entityManager获取对象……除非我缺少什么东西——我可能是这样!”我仍然不知道答案。。tnx!使用eager fetch类型,当调用event=(event)em.createQuery(“从事件e中选择对象(e),其中e.eventCID=55000”).getSingleResult()时,将获取所有关系;。我认为这就是为什么XML中有所有关系,但我不明白jaxb的字段访问如何修复它。唯一的想法是你没有这个领域的获得者。
@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) {
}
}