Hibernate多对一映射中的EntityNotFoundException但是数据存在

Posted

技术标签:

【中文标题】Hibernate多对一映射中的EntityNotFoundException但是数据存在【英文标题】:EntityNotFoundException in Hibernate Many To One mapping however data exist 【发布时间】:2012-11-12 09:46:03 【问题描述】:

当我尝试通过 Invoice 对象获取用户时出现 javax.persistence.EntityNotFoundException 错误

invoice.getUser().getId()

错误如下

javax.persistence.EntityNotFoundException: Unable to find com.indianretailshop.domain.User with id 5
    at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:137)
    at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:189)
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:178)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:215)

实体类如下(不包括getter和setter)

@Entity
@Table(name="users")
public class User implements Serializable 
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(unique=true, nullable=false)
    private int id;

    .
        .
        .

    //bi-directional many-to-one association to Invoice
    @OneToMany(mappedBy="user")
    private List<Invoice> invoices;


@Entity
@Table(name="invoice")
public class Invoice implements Serializable 
    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(unique=true, nullable=false)
    private int id;
        .
        .
        .

    //bi-directional many-to-one association to User
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="Users_id")
    private User user;

【问题讨论】:

要获得答案,您需要提供更多信息,例如:您到底在做什么?完成堆栈跟踪...并仔细检查该实体是否确实存在于数据库中。 您是否定义了从发票表到用户表的外键?正如@Ralph 所说,您应该检查给定用户(ID 为 5)是否确实存在。 当我使用 LAZY fetch 时它正在工作,是的,数据库中有实体。我不明白为什么它在 EAGER fetch 中不起作用,其余代码与以前相同。现在我使用 LAZY fetch 作为临时更改来解决问题。 我从未使用 setid() 方法定义 id,这意味着它仅从数据库中获取 id,并且它们是数据库中存在的外键。这是休眠中的错误 我还注意到,如果我在数据库中创建两张发票,那么即使 EAGAR fetch 也能正常工作,所以问题似乎只存在于一个用户的一张发票记录中。 【参考方案1】:

问题可能是直接实体不存在,也可能是来自该实体的引用实体,通常是 EAGER 提取类型,或者 optional=false。

试试这个:

     //bi-directional many-to-one association to User
     @ManyToOne(fetch=FetchType.LAZY)
     @JoinColumn(name="Users_id")
     private User user = new User();

【讨论】:

之前我使用 LAZY fetch 时它才起作用,但它在我不明白的 EAGER fetch 中不起作用。 这是一个错误还是我应该报告的东西。 @kakawat 我也遇到了和上面一样的问题,但是代码不在我们的控制范围内,我删除了数据库中的一些行,不正确的数据会不会导致这种错误 Lazy fetch 最终会引发错误,因为当您尝试引导本来会急切地获取的东西时,您最终会遇到 LazyLoadException。我希望我能理解为什么它不能开始。我在 Spring Boot 1.5.1 中运行 Hibernate 5.0.11 我面临同样的问题,FetchType.Lazy 并没有解决我的问题。在我的情况下,这种关系不是双向的,我只声明了 @ManyToOne。我将 java-ee-api-7.0.jar 用于 JPA 而不是 Hibernate。只有当我给出 NotFoundannotation 时才会发生异常。知道我可能做错了什么吗?【参考方案2】:

如果使用@ManyToOne,则引用的实体必须存在。唯一的其他选择是将该字段指定为 long 并通过单独的查询检索引用的实体。

如果找不到请求的实体,则抛出异常 (javax.persistence.EntityNotFoundException) 而不是返回 null。

如果您是延迟加载且未手动处理此异常,请使用@NotFound 注解解决此异常。

 @ManyToOne(
        fetch = FetchType.LAZY)
    @NotFound(
        action = NotFoundAction.IGNORE)
    @JoinColumn(
        name = COLUMN,
        referencedColumnName = COLUMN,
        insertable = false,
        updatable = false)
    private Table table;

【讨论】:

【参考方案3】:

我遇到了同样的问题,并且

@NotFound(action = NotFoundAction.IGNORE)

解决了我的问题。

【讨论】:

@dirai 我没试过。当您不介意关联实体是否存在时,NotFound 无论如何都是实用的。 唯一的问题是它会默默地失败。有没有人找到更好的解决方案,可以优雅地处理此错误,同时记录丢失的链接? 使用时请注意这会导致性能问题!修复不一致的数据就可以了。【参考方案4】:

我最近遇到了类似的问题,但问题是数据库中始终存在记录。所以我做了一些调查,发现在从数据库重新加载之前缓存实体被标记为删除和重新加载失败。它发生在Hibernate 4.3.5 Final 对我来说 然后我升级到Hibernate 4.3.11 Final,这似乎解决了这个问题。

【讨论】:

简单。简单。快点。很好的解决方案!【参考方案5】:

不确定这是否适用于您的情况。

但我有一个类似的问题,我直接在数据库表 X 中更新并将字段设置为 null,但在 java 类中,该字段是@NotNull。

所以当另一个类 Y 有一个带有 ManyToOne 的 X 对象时,由于实体中的 null 值,它无法加载实体。

【讨论】:

谢谢,这是我的问题。寻找@NotNull@JoinColumn([...]nullable = false) @Negal,您的评论实际上是该线程中对该问题的唯一真正解释。其他评分最高的答案只是解决方法。【参考方案6】:

请尝试以下方法

@OneToMany(mappedBy="yourMappingattributeName",cascade=CascadeType.ALL)

@OneToMany(mappedBy="yourMappingattributeName",cascade=CascadeType.MERGE)

【讨论】:

【参考方案7】:

使用 @NotFound(action = NotFoundAction.IGNORE) 以防它的父级不存在

使用 cascade=CascadeType.ALL 会删除它的父实体

【讨论】:

我在多对一中遇到了同样的问题,延迟加载。当我添加 @NotFound(action = NotFoundAction.IGNORE) 时,它解决了问题。【参考方案8】:

也许有人来到这个答案并发现它很有用:就我而言,我已将我的实体标记为已删除,与该实体有关系的实体找不到它。因此,将 deleted 更改为 false 对我有用。

【讨论】:

【参考方案9】:

当您在 @JoinColumns@ManyToOne 注释中添加 referencedColumnName = COLUMN 时,它应该可以工作

【讨论】:

【参考方案10】:

您必须为所有实体实现 hashCode 和 equals 方法。 示例:

@Override
public int hashCode() 
    return Objects.hash(getId());

【讨论】:

以上是关于Hibernate多对一映射中的EntityNotFoundException但是数据存在的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate单向多对一映射关系

Hibernate的关联关系映射

一口一口吃掉Hibernate——多对一单向关联映射

Hibernate,关系映射的多对一单向关联多对一双向关联一对一主键关联一对一外键关联多对多关系关联

Hibernate多对一,多对多的表映射关系

--------------Hibernate学习 多对一映射 和 一对多映射