【发布时间】:2021-09-10 18:48:47
【问题描述】:
我有以下两个通过多对多关系链接的实体
data class GroupEntity(
@Id
val id: String,
val name: String
) {
@ManyToMany
val users: MutableSet<UserEntity> = HashSet()
}
@Entity
data class UserEntity(
@Id
val id: UUID,
val name: String,
@ElementCollection
val interests: Set<InterestEmbeddable> = HashSet(),
@ElementCollection
val badges: Set<BadgeEmbeddable> = HashSet()
) {
@ManyToMany(mappedBy = "users")
val groups: MutableSet<GroupEntity> = HashSet()
}
每个实体都有一个对应的JpaRepository。
每当我尝试将user 添加到group 时,hibernate 都会在后台对数据库进行许多查询。它实际上从group 的每个user 中加载每个interests 和badges 我正在尝试将我的user 添加到。
var group = this.groupRepository.getById(groupId);
var user = this.userRepository.getById(userId);
group.getUsers().add(user);
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
Hibernate: select interests0_.user_entity_id as user_en1_47_0_, interests0_.name as name2_47_0_, interests0_.value as value3_47_0_ from user_entity_interests interests0_ where interests0_.user_entity_id=?
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
Hibernate: select interests0_.user_entity_id as user_en1_47_0_, interests0_.name as name2_47_0_, interests0_.value as value3_47_0_ from user_entity_interests interests0_ where interests0_.user_entity_id=?
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
Hibernate: select interests0_.user_entity_id as user_en1_47_0_, interests0_.name as name2_47_0_, interests0_.value as value3_47_0_ from user_entity_interests interests0_ where interests0_.user_entity_id=?
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
Hibernate: select interests0_.user_entity_id as user_en1_47_0_, interests0_.name as name2_47_0_, interests0_.value as value3_47_0_ from user_entity_interests interests0_ where interests0_.user_entity_id=?
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
Hibernate: select interests0_.user_entity_id as user_en1_47_0_, interests0_.name as name2_47_0_, interests0_.value as value3_47_0_ from user_entity_interests interests0_ where interests0_.user_entity_id=?
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
Hibernate: select interests0_.user_entity_id as user_en1_47_0_, interests0_.name as name2_47_0_, interests0_.value as value3_47_0_ from user_entity_interests interests0_ where interests0_.user_entity_id=?
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
Hibernate: select interests0_.user_entity_id as user_en1_47_0_, interests0_.name as name2_47_0_, interests0_.value as value3_47_0_ from user_entity_interests interests0_ where interests0_.user_entity_id=?
Hibernate: select badges0_.user_entity_id as user_en1_46_0_, badges0_.badge_id as badge_2_46_0_ from user_entity_badges badges0_ where badges0_.user_entity_id=?
您可以想象这会导致我出现性能问题。顺便说一下,我在尝试删除用户时遇到了同样的问题。
如何避免这些额外的查询?
我一直在阅读Best pratice to avoid selecting all rows when adding to owning side collection of a @ManyToMany,但我对那里提供的答案并不满意。如果可能,我想避免将连接表具体化为实体。
【问题讨论】:
-
我不希望发生这种情况。首先,您能否澄清一下您是否有任何相等或哈希码的实现——通过 lombok 或其他方式——可能会引用所有字段?
-
我正在使用 Kotlin 数据类,所以我正在使用它提供的 equals / hashcode。这意味着不考虑组和用户可变集,因为它们在正文中声明。
-
@AlanHay 好的,我想我从你的回答中知道了。事实上,我的其他 2 个集合是 equals / hashcode 的一部分,这使得休眠加载集合。通过将它们移出等号/哈希码,我不再获得多个查询。
标签: hibernate jpa spring-data-jpa many-to-many