【问题标题】:Hibernate JOIN ON generates invalid queryHibernate JOIN ON 生成无效查询
【发布时间】:2016-11-04 10:09:57
【问题描述】:

我需要列出所有Product 记录,无论它们是否有对应的ForeignProductInfoProduct 没有引用 ForeignProductInfo

我正在使用这个 JPA 查询:

@Query("select distinct fpi from Product pp "
        + "left join fetch ForeignProductInfo fpi on fpi.partner.id = :partnerId "
        + "left join fetch fpi.product p ") 
public List<ForeignProductInfo> loadAllForPartner(@Param("partnerId") Long partnerId);

这一直有效,直到我添加第二个连接(以避免在访问 ForeignProductInfo.product 时选择 n+1)。然后它会生成这个 SQL:

SELECT 
    foreignpro1_.id AS id1_7_0_,
    product2_.id AS id1_12_1_,
    productsub3_.id AS id1_18_2_,
    productgro4_.id AS id1_14_3_,
    foreignpro1_.code AS code2_7_0_,
    foreignpro1_.name AS name3_7_0_,
    foreignpro1_.partner_id AS partner_4_7_0_,
    foreignpro1_.product_id AS product_5_7_0_,
    product2_.a AS a2_12_1_,
    product2_.b AS b3_12_1_,
    product2_.comment AS comment4_12_1_,
    product2_.conversionMethod AS conversi5_12_1_,
    product2_.diaMax AS diaMax6_12_1_,
    product2_.diaMin AS diaMin7_12_1_,
    product2_.len AS len8_12_1_,
    product2_.mu AS mu9_12_1_,
    product2_.name AS name10_12_1_,
    product2_.nameLang1 AS nameLan11_12_1_,
    product2_.nameLang2 AS nameLan12_12_1_,
    product2_.productSubGroup_id AS product15_12_1_,
    product2_.surfaceMax AS surface13_12_1_,
    product2_.surfaceMin AS surface14_12_1_,
    productsub3_.name AS name2_18_2_,
    productsub3_.productGroup_id AS productG3_18_2_,
    productgro4_.name AS name2_14_3_,
    productgro4_.seq AS seq3_14_3_
FROM
    Product product0_
        LEFT OUTER JOIN
    ForeignProductInfo foreignpro1_ ON (foreignpro1_.partner_id = 3);

如您所见,第二个 JOIN 丢失并导致异常:

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Unknown column 'product2_.id' in 'field list'

编辑:ForeignProductInfo 对于每个 ProductPartner 的组合有零个或一个记录。

@Entity
public class ForeignProductInfo {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    private Partner partner;

    @ManyToOne
    private Product product;

    @Column(length=50)
    @Size(max=50)
    private String code;

    @Column(length=200)
    @Size(max=200)
    private String name;
    ...
}

【问题讨论】:

  • 如果我做对了,在你的架构中ForeignProductInfo.product 指向原始的Product,对吗?
  • 如果是这样,您的显式声明 on fpi.partner.id = :partnerId 似乎覆盖了将生成的任何 on 条件,如我们所见。它仅根据您的条件生成查询。我猜你不需要第二次加入,如果你需要更详细,只需使用on fpi.partner.id = :partnerId and fpi.product = ppon fpi.partner.id = :partnerId and fpi.product.id = pp.id
  • 是的,它指向原始的Product,它也有一些需要获取的关系。不幸的是,您建议的解决方案在查询验证期间失败:Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list
  • 好吧,我对此的最后一个想法是删除第二个连接和 on 子句以使用隐式连接,并使用带有 fpi.partner.id = :partnerId or fpi.partner is null 的 where 子句
  • 查询没有什么意义,因为它引入了“pp”作为候选,但没有使用它。如果不使用 fpi,则更容易将 fpi 作为候选者。

标签: hibernate jpa


【解决方案1】:

我在 3 天内无法解决这个问题。这是 SQL 中最简单的事情,但在 JPA 中似乎不可能实现。也尝试了条件API,但无法进行条件提取,只能条件加入。

我最终遍历了 Product 的列表,并一一加载了他们的 ForeignProductInfo。 :( 然后放弃了 JPA 并为此使用了纯 SQL。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    相关资源
    最近更新 更多