【问题标题】:OneToOne + No Foreginkey + Unidirectional + Datamissing => EntityNotFoundExceptionOneToOne + 无 Foreginkey + 单向 + Datamissing => EntityNotFoundException
【发布时间】:2014-10-15 18:33:44
【问题描述】:

在旧系统中,我们有 1 个表(实体)和 1 个视图(UserDetail),没有约束但有关系。

Entity
| Id | Desc | Created_By |...

UserDetail
| UserId | F_Name | L_Name |...

CreatedBy 具有创建该实体的用户的用户 ID。我们在 Entity.java 中有一个单向映射,如下所示。

@OneToOne
@JoinColumn(name = "CREATED_BY", referencedColumnName = "USER_ID")
private UserDetail createdBy;

问题

但由于它是一个遗留系统,我们无法控制它并且用户被硬删除。

调用 entityReposity.findAll 时,抛出以下错误

org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find com...UserDetail with id 92237; nested exception is javax.persistence.EntityNotFoundException: Unable to find com...UserDetail with id 92237

问题

如何让 JPA 认为此关联是可选的,或者 JPA 中有什么方法可以忽略它(如 Hibernate 中的 @NotFound)?

试过

  1. @NotFound 有效,但我们需要将@OneToOne 破解为@ManyToOne。我们还需要一个独立于实现的解决方案。 也注意到了这个bug,https://hibernate.atlassian.net/browse/ANN-725

  2. optional=true - 如果这能按照它应该如何表现的句法含义起作用,我就不会写这个了。

  3. 还尝试了 UserDetails.java 中的 postLoad()。

  4. @PostLoad solution 我们有 aop 异常处理程序,并且在调用实体类中的 @PostLoad 之前捕获异常。

在 Entity.java 中

    @PostLoad
    public void postLoad(){
        try {
            System.out.println(this.getCreatedBy()); //Before control comes here, it goes to aop exception handler
        }
        catch (EntityNotFoundException e){
            setCreatedBy(null);   
        }
    }

任何帮助将不胜感激。

【问题讨论】:

  • 可选=真有什么问题?如果你有这个设置,你能打印出 Hibernate 生成的查询吗?我之前在 OneToMany 关系上使用 optional=true 就好了。您可能想尝试的另一种可能性是使用 JoinColumn,并且 nullable = true
  • optional=true 没有做任何事情,没有错误。将查找代码库并尝试获取查询。
  • 你能发布你的 persistence.xml 吗? (至少是您提供的域所需的部分)...此外:您正在使用或“绑定”使用哪个版本的 JPA?
  • 添加属性 inverse = "false" 。它将使关系单向,并且永远不会尝试从 UserDetail 表中获取记录。
  • 您是使用 Session.load 还是使用 JPQL 查询加载该对象?某些注解或参数仅在通过其 ID 加载对象时才有效。

标签: java hibernate jpa oracle11g one-to-one


【解决方案1】:

虽然听起来很疯狂,但您需要建立@OneToOne 关联optional = false。请参阅this question and answer 了解说明。

所以关联的代码是:

@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "CREATED_BY", referencedColumnName = "USER_ID")
private UserDetail createdBy;

当然麻烦的是,如果你尝试访问关联的createdBy 关联,那么Hibernate 会尝试延迟加载关联的Entity,你会得到同样的异常。

@NotFound 确实是您的最佳选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-09-28
    • 2019-04-01
    • 2012-03-14
    • 2015-04-17
    • 2014-05-17
    • 1970-01-01
    • 1970-01-01
    • 2014-11-09
    相关资源
    最近更新 更多