OneToOne + No Foreginkey + Unidirectional + Datamissing => EntityNotFoundException

时间:2014-08-22 00:31:49

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

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

Entity
| Id | Desc | Created_By |...

UserDetail
| UserId | F_Name | L_Name |...

CreatedBy具有创建该实体的用户的用户标识。我们在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。我们还想要一个独立于实现的解决方 也注意到这个错误,https://hibernate.atlassian.net/browse/ANN-725

  2. optional = true - 如果按照它应该如何运作的语法含义工作,我就不会写这个。

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

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

  5. 在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);   
            }
        }
    

    任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:3)

听起来很疯狂,你需要建立@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将尝试延迟加载关联的实体,您将获得相同的异常。

@NotFound真的是你最好的选择。