JPA+HIBERNATE:多对多关系中的笛卡尔积

Posted

技术标签:

【中文标题】JPA+HIBERNATE:多对多关系中的笛卡尔积【英文标题】:JPA+HIBERNATE: cartesian product in Many-to-Many relationship 【发布时间】:2016-05-04 19:51:30 【问题描述】:

我试图解释问题。我有一个具有多对多关系的实体

@Entity
@Table(name="TABLE1")
public class Table1 implements Serializable 

...

//bi-directional many-to-many association to Table1
@ManyToMany
@JoinTable(
    name="TABLE2"
    , joinColumns=
        @JoinColumn(name="ID_ELEMENTS1")
        
    , inverseJoinColumns=
        @JoinColumn(name="ID_ELEMENTS2")
        
    )
private List<Table1> elements;

//bi-directional many-to-many association to Table1
@ManyToMany(mappedBy="elements")
private List<Table1> elementOf;

...


数据库表是:

TABLE1
ID      ...
55499   ...
55498   ...
55497   ...

TABLE2
ID_ELEMENTS1    ID_ELEMENTS2
55499           55498
55499           55497

当我尝试执行以下 jpql 查询时

SELECT  
    t  
FROM  
    Table1 t  
    LEFT JOIN FETCH t.elementOf 
WHERE  
    t.id = 55499

result 是一个包含 两个 元素(id 为 55499)的数组列表,每个元素都有一个包含两个元素的数组列表(一个 id 为 55498,一个 id 为 55497)。我想获得的结果是 one 元素(id 为 55499),其中包含两个元素的 arraylist(一个 id 为 55498,一个 id 为 55497)。 我希望我很清楚。能否帮我优化一下java对象结果(我依稀记得eclipselink中的QueryHints.BATCH)?

【问题讨论】:

【参考方案1】:

您在查询中指定了join,这就是被执行的内容。 JPA 提供程序不会自动删除重复项。

您只需在查询中添加distinct 即可删除所有重复项:

SELECT  
    DISTINCT t  
FROM  
    Table1 t  
    LEFT JOIN FETCH t.elementOf 
WHERE  
    t.id = 55499

【讨论】:

以上是关于JPA+HIBERNATE:多对多关系中的笛卡尔积的主要内容,如果未能解决你的问题,请参考以下文章

如何在多对多关系上使用休眠和 JPA 删除孤立实体?

MySQL 基础 -- 多表关系(一对一1对多(多对一)多对多)多表查询(内连接外连接自连接子查询(嵌套查询)联合查询 union)笛卡儿积

更新多对多关系中的实体

多对多关系:org.hibernate.MappingException:无法确定类型:java.util.Set

mysql 多对多映射关系的筛选SQL怎么写

多对多关系中的 JPA 条件查询