Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jpa 为什么在使用实体图查询将加载我的惰性属性之前,我必须从EclipseLink共享缓存中逐出我的实体?_Jpa_Jakarta Ee_Eclipselink_Derby - Fatal编程技术网

Jpa 为什么在使用实体图查询将加载我的惰性属性之前,我必须从EclipseLink共享缓存中逐出我的实体?

Jpa 为什么在使用实体图查询将加载我的惰性属性之前,我必须从EclipseLink共享缓存中逐出我的实体?,jpa,jakarta-ee,eclipselink,derby,Jpa,Jakarta Ee,Eclipselink,Derby,在使用EclipseLink 2.7.4和Derby 10.14.2.0更新运行在GlassFish 5.1.0上的Jakarta EE应用程序中的实体之前,我将更新的实体与保存的实体进行比较,并记录更改。我最近注意到,我的比较代码不适用于@OneToMany关系属性和@ElementCollection属性,我跟踪到了@OneToMany和@ElementCollection属性的延迟加载问题。我能够使用fetch属性解决问题,如下所示: 获取渴望的实体 @Entity public clas

在使用EclipseLink 2.7.4和Derby 10.14.2.0更新运行在GlassFish 5.1.0上的Jakarta EE应用程序中的实体之前,我将更新的实体与保存的实体进行比较,并记录更改。我最近注意到,我的比较代码不适用于@OneToMany关系属性和@ElementCollection属性,我跟踪到了@OneToMany和@ElementCollection属性的延迟加载问题。我能够使用fetch属性解决问题,如下所示:

获取渴望的实体

@Entity
public class Container implements Serializable {

    @OneToMany(mappedBy = "container", fetch = FetchType.EAGER)
    private List<AssetSerial> assets;

    @ElementCollection (fetch = FetchType.EAGER)
    private List<Reference> references;
@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedEntityGraph(
    name = "Container.eager",
    attributeNodes = {
            @NamedAttributeNode("assets"),
            @NamedAttributeNode("references") })
public class Container implements Serializable {
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.loadgraph", em.getEntityGraph("Container.eager"));

Container managedContainer = em.find(Container.class, updatedContainer.getId(), props);

PersistenceUnitUtil tester = em.getEntityManagerFactory().getPersistenceUnitUtil();

logger.debug("Assets: {}", tester.isLoaded(managedContainer, "assets"));
logger.debug("References: {}", tester.isLoaded(managedContainer, "references"));
实体管理器初始化

@PersistenceContext(unitName = "MYPU")
private EntityManager em;
查找每个实体只工作一次的方法

@Entity
public class Container implements Serializable {

    @OneToMany(mappedBy = "container", fetch = FetchType.EAGER)
    private List<AssetSerial> assets;

    @ElementCollection (fetch = FetchType.EAGER)
    private List<Reference> references;
@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedEntityGraph(
    name = "Container.eager",
    attributeNodes = {
            @NamedAttributeNode("assets"),
            @NamedAttributeNode("references") })
public class Container implements Serializable {
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.loadgraph", em.getEntityGraph("Container.eager"));

Container managedContainer = em.find(Container.class, updatedContainer.getId(), props);

PersistenceUnitUtil tester = em.getEntityManagerFactory().getPersistenceUnitUtil();

logger.debug("Assets: {}", tester.isLoaded(managedContainer, "assets"));
logger.debug("References: {}", tester.isLoaded(managedContainer, "references"));
Map props=newhashmap();
put(“javax.persistence.loadgraph”,em.getEntityGraph(“Container.eager”);
Container managedContainer=em.find(Container.class,updatedContainer.getId(),props);
PersistenceUnitUtil tester=em.getEntityManagerFactory().getPersistenceUnitUtil();
debug(“资产:{}”,tester.isLoaded(managedContainer,“资产”);
debug(“References:{}”,tester.isLoaded(managedContainer,“References”);
不幸的是,isLoaded测试方法仅在我第一次调用特定实体上的find方法时返回true。第二次和后续时间isLoaded返回false。我与这个问题斗争了好几个小时,确定这个问题是EclipseLink共享缓存没有遵守我传递给find方法的实体图提示。我通过在调用find之前立即从缓存中逐出实体解决了这个问题,如下所示

找到有效的方法

em.getEntityManagerFactory().getCache().evict(Container.class, updatedContainer.getId());

Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.loadgraph", em.getEntityGraph("Container.eager"));

Container managedContainer = em.find(Container.class, updatedContainer.getId(), props);

PersistenceUnitUtil tester = em.getEntityManagerFactory().getPersistenceUnitUtil();

logger.debug("Assets: {}", tester.isLoaded(managedContainer, "assets"));
logger.debug("References: {}", tester.isLoaded(managedContainer, "references"));
em.getEntityManagerFactory().getCache().Recit(Container.class,updatedContainer.getId());
Map props=newhashmap();
put(“javax.persistence.loadgraph”,em.getEntityGraph(“Container.eager”);
Container managedContainer=em.find(Container.class,updatedContainer.getId(),props);
PersistenceUnitUtil tester=em.getEntityManagerFactory().getPersistenceUnitUtil();
debug(“资产:{}”,tester.isLoaded(managedContainer,“资产”);
debug(“References:{}”,tester.isLoaded(managedContainer,“References”);
现在isLoaded测试总是返回true,并且我能够在更新的实体中记录所有更改

总之,我有以下问题:

  • 为什么EclipseLink不尊重我的实体图
  • 手动将实体从缓存中逐出是否会遇到问题
  • 有没有更好的方法来强制EclipseLink初始化我的延迟加载属性

您没有明确提到在isLoaded不起作用时如何加载实体,但似乎是实体图支持中的一个缺陷。在我看来,数据可能已加载到共享缓存中,并且它标记了已应用的加载图,因此无需执行任何特殊操作,但出于性能原因,为本地EntityManager克隆此共享缓存实例的逻辑将替换与未迁移值持有者的急切关系。或者它可能是isLoaded检查本身的一个bug。如果你在没有逐出的情况下访问关系,你会收到DB查询吗?@Chris我为延迟响应道歉。我错过了通知我你对我的帖子发表评论的电子邮件。为了回答您的问题,我使用em.find方法加载了实体,如这两种情况的帖子所示。我不记得细节,但我相信我只在em.find过程中看到了DB查询,在我第一次逐出实体的情况下。我应该用EclipseLink将此记录为一个bug吗?绝对要归档一个bug。手动从缓存中逐出实体将导致额外的数据库命中;如果您可以忍受不使用逐出,我建议您尝试,因为这是为了在您确实需要刷新数据时使用。您需要通过检查访问这些未加载的属性是否会导致DB命中来检查tester.isLoaded方法是否存在问题。我怀疑,只要共享会话缓存仍然具有实体并且仍然可以从中读取,就不会出现数据库命中(即,如果不直接使用更新/删除查询或刷新更改)