java Hibernate一对多列表中的重复结果

ffvjumwh  于 2023-01-07  发布在  Java
关注(0)|答案(3)|浏览(129)

我已经将一个1:N关系Map到一个@OneToMany列表,但是当我访问这个列表时,由于一个OUTER JOIN,结果是重复的。

@Entity
public class Programmer

    @ElementCollection(fetch=FetchType.EAGER)
    @CollectionTable(name="emails", joinColumns=@JoinColumn(name="id", nullable=false))
    @Column(name="email", nullable=false)
    protected Set<String> emails = new HashSet<String>();

    @OneToMany(mappedBy="programmer", fetch=FetchType.EAGER)
    private List <Game> games = new ArrayList<Game>();

当我使用prog.getGames()获取属性时,结果会重复,因为Hibernate SQL进行了一个OUTER JOIN:

from programmer 
left outer join emails on programmer.id=emails.id 
left outer join game on programmer.id=game.id
where programmer.id=?

有没有不把列表转换成集合的解决方案?我需要用prog.getGames()获取游戏,不能使用自定义的HQL或标准。

6vl6ewon

6vl6ewon1#

虽然Set<>的使用从根本上解决了您的问题,但我认为这只是一个创可贴,以获得您所追求的预期结果,但它在技术上并没有解决根本问题。
您最终应该使用默认的延迟获取策略,因为我认为急切地加载任何关联,特别是基于集合的关联,都是特定于查询的,因此应该在您构造特定查询时切换,而不应作为实体Map模型的一部分受到影响。
考虑一下将来你添加一个新的查询,但是你只对聚合根实体的属性感兴趣。你的Map模型仍然会强制急切地获取这些关联,你会消耗额外的资源,因为有一个更大的持久性上下文,这意味着更多的内存消耗,并对你不打算使用的东西强制不必要的数据库连接。
如果有多个集合需要水合,我建议您考虑使用FetchMode.SUBSELECT代替。
如果我们假设您的查询返回10个实体,则具有2个集合的默认惰性策略将发出21个查询(1个用于基本结果集,2个用于每个加载的实体)。
SUBSELECT的好处是Hibernate实际上只会发出3个查询(1个用于基本结果集,1个用于每个集合,以加载所有实体的所有集合元素)。显然,根据特定的查询,将一个带有左连接的查询分解为3个查询实际上在数据库级别也可以执行得更好。

qij5mzcb

qij5mzcb2#

我已经用@Fetch(FetchMode.SUBSELECT)解决了这个问题

sycxhyv7

sycxhyv73#

我遇到了同样的问题。companyUserRelations有重复的对象(我的意思是指向同一对象的相同指针,而不是重复的数据)
所以在阅读@dimitry response之后,我添加了@Fetch(FetchMode.SUBSELECT),它工作了

相关问题