实体未找到异常:使用JPA - Hibernate进行LEFT JOIN

3

主线程中的异常 "main" javax.persistence.EntityNotFoundException: 无法找到 ID 为 00001388000307 的 CNPJ

我正在阅读 JPA 文档,我发现当尝试访问实体(通过 EntityManger 接口的 getReference 方法)但实体不存在时,会抛出此异常。

当通过 EntityManager.getReference 获取的实体引用被访问但实体不存在时,持久性提供程序抛出此异常。

我有这些实体:SalesmanCNPJ。可能存在许多具有相同 CNPJ 的销售员,换句话说,是一个 @ManyToOne 关系。

这个关系正常工作。

但是,当我尝试执行查询时:

select r from Salesman r join fetch r.yearMonth left join fetch r.cnpj

为了将销售员与其年月(它正在工作!)关系和其CNPJ关系一起带来,当我尝试执行左连接时,会抛出异常,如我所提到的。

当我不执行LEFT JOIN时,非常好,所有销售员都有他的CNPJs,没有任何异常,但是,有些销售员没有CNPJ,我也必须将它们带来,因此需要执行LEFT JOIN

@Entity
public class Salesman{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @JoinColumn(name = "year_month")
    @ManyToOne
    private YearMonth yearMonth;

    private String cnpjS;

    @JoinColumn(name = "cnpj")
    @ManyToOne
    private CNPJ cnpj;

    public AnoMes getYearMonth() {
        return yearMonth;
    }

    public CNPJ getCnpj() {
        return cnpj;
    }

}

@Entity
public class CNPJ {

    @Id
    @Column(name = "CCG", length = 14)
    private String ccg;

    public String getCcg() {
        return ccg;
    }
}

Hibernate 生成的选择器:

select *
from salesman s
inner join yearmonth y on s.ano_mes = y.id 
left outer join cnpj c on s.cnpjS = c.CCG

这个咨询返回这些值,rcnpj是销售员的CNPJ,bcnpj是来自CNPJ的。一些销售员带有空的CNPJ,我认为这可能是问题所在。但我不这么认为。

The return of the select

2个回答

2
尝试使用<property name="show_sql">true</property>启用Hibernate SQL日志记录,以查看实际查询(本机,在数据库上调用)的样子,也许在Hibernate处理后有一个内部连接。
要更改它,您可以尝试使用@Column(nullable=true)注释来处理您的关系或@Fetch(FetchMode.SELECT)以查看实际查询将如何更改。
原因是您引用了ID为00001388000307的cnpj,但是这样的cnpj行不存在。
您可以尝试使用@NotFound(action=NotFoundAction.IGNORE)跳过此错误,但建议修复您的数据库或处理异常。

我把日志放在了帖子里。 - Henrique Santiago
我已经尝试过添加@Column(nullable=true)和@Fetch(FetchMode.SELECT),但仍然出现相同的错误。 - Henrique Santiago
我相信你有一行引用了ID为00001388000307的cnpj,但是在cnpj表中没有这样的行。你能检查一下吗?因此,并不是空值,而是cnpj的ID不存在,这是异常的原因。 - staszko032
是的,我有一个销售员,其CNPJ为'00001388000307',但我没有在其ID为'00001388000307'的CNPJ注册处注册。 - Henrique Santiago
我添加了注解@NotFound(action=NotFoundAction.IGNORE),但是出现了“n+1”查询。 - Henrique Santiago

2
您正在将Salesman表中的cnpj列用作外键和值列。在这种情况下,@staszko032的建议使用@NotFound(action=NotFoundAction.IGNORE)似乎会按照您的期望工作。
但是,如果可能的话,我认为您应该重构您的模型。您可以始终创建一个CNPJ实体,在这种情况下,您将不会有没有与CNPJ相关联的Salesman,并且可以使用INNER JOIN,或者使用2个列,一个用于当Salesman没有具体相关联的CNPJ时(值为字符串),另一个用于当它有(外键)。

这个 CNPJ 实体不是我创建的。我在项目中收到了它,所以必须使用 :( - Henrique Santiago
我添加了注解@NotFound(action=NotFoundAction.IGNORE),但是出现了“n+1”查询。 - Henrique Santiago

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接