【发布时间】:2016-11-04 10:09:57
【问题描述】:
我需要列出所有Product 记录,无论它们是否有对应的ForeignProductInfo。 Product 没有引用 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 对于每个 Product 和 Partner 的组合有零个或一个记录。
@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 = pp或on 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 作为候选者。