如何使用JPA解决javax.persistence.EntityNotFoundException(而不是使用@NotFound)

时间:2012-09-04 10:29:56

标签: java hibernate jpa persistence

我们正在使用JPA从数据库加载一些东西。某些实体可能在它们之间具有可选关系,例如

@Entity
public class First {
    ....
    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
    @JoinColumns(value = {
        JoinColumn(name = "A_ID", referencedColumnName = "A_ID", insertable = false, updatable = false), 
        JoinColumn(name = "B_ID", referencedColumnName = "B_ID", insertable = false, updatable = false)})
    private Second second;

当数据库中存在此关联时,一切正常。如果不是,我会得到javax.persistence.EntityNotFoundException 如果关联不存在,我想要的是将此字段设为NULL而不是异常。

我尝试了几种不同的东西,例如在关系注释中使用optional = true(btw是默认选项),将其设置为Nullable等。似乎没有什么可以做到的,似乎所有这些选项都被忽略了。

我发现很多链接提到了这个相同的问题(以及stackoverflow中的一些问题)但是在所有这些问题中,建议使用Hibernate中的@NotFound注释。但是我们不想对Hibernate有任何依赖(我们希望保持所有纯粹的JPA)。

你们其中任何人都知道解决这个问题的其他方法吗?

非常感谢你的帮助!

6 个答案:

答案 0 :(得分:7)

以下是此问题的替代解决方案。我不得不建立在一个旧数据库的基础上,这个数据库的关系有时会被破坏。这就是我只使用JPA解决它的方法。

@PostLoad
public void postLoad(){
    try {
        if(getObject() != null && getObject().getId() == 0){
            setObject(null);
        }
    }
    catch (EntityNotFoundException e){
        setObject(null);
    }
} 

答案 1 :(得分:2)

我遇到了同样的问题。它并不总是可重复的,所以我无法测试它,但这里有一些想法:

  
      
  1. 第二个类的实例被删除,而First类的实例对此一无所知。
  2.   
  3. 当删除其第二个实例时,您需要一种让First知道实例知道的方法。
  4.   
  5. 用于删除的级联选项在这里没有用。
  6.   
  7. 当Second实例存在于Second实例中时,您可以尝试使用双向关系。它让你更新实例   首先通过第二个实例,然后删除第二个
  8.   
  9. 双向关系 - 是邪恶的。在你的情况下,我认为,First - 是Second的所有者。不允许任何服务删除你的   二次直接。让服务与实例一起工作   首先删除Second的实例。在这种情况下,你可以做到   “第二个”字段可以为空,首先是删除第二个实例   EntityManager的。
  10.   
  11. 执行查询时可能会出现异常,并且启用了第二级缓存并且查询有提示,这样可以缓存其结果。一世   会通过以下方法为您提供查询结果:
  12.   
private List<?> getQueryResult(final Query query)
{
    try
    {
        return query.getResultList();
    }
    catch (EntityNotFoundException e)
    {
        return query.setHint("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH).getResultList();
    }
}
  
      
  1. 如果您通过EntityManger处理实体,但不通过查询,并且由于实体被缓存而导致异常,则可能会使所有实体无效   删除第二个时在缓存中的First实体。
  2.   

我想讨论这个解决方案,因为我无法测试它,也无法让它变得有效。如果有人试图,请告诉我。

PS:如果有人对hibernate进行了单元测试,那就重现了这个问题,请你告诉我。我希望进一步调查。

答案 2 :(得分:2)

删除关联的实体ID时会发生这种情况。在我的情况下,我有产品表取决于品牌表。我删除了一个品牌ID的行或实体,其中一个产品实例依赖于它。

答案 3 :(得分:0)

如何在对应的实体类中添加测试:

public boolean getHasSecond() {
    if (this.Second != null) {
        return true;
    } else {
        return false;
    }
}

像这样,您可以检查关系是否存在......

答案 4 :(得分:0)

尝试在OneToOne注释上添加optional = true。

答案 5 :(得分:-1)

尝试在@OneToMay(******)中使用cascade=CascadeType.ALL