英文:
Hibernate - join ElementCollection with the rest of an entity fetch query
问题
我尝试将实体映射为响应时遇到了严重的性能问题。
这是实体部分:
@Entity
@Table(name = "MyEntity")
public class MyEntity extends BaseEntity {
@Column(name = "someOtherId", nullable = false)
private String someOtherId;
@ElementCollection
@CollectionTable(name = "Phones", joinColumns = @JoinColumn(name = "myEntityId"))
@Column(name = "phone")
private List<String> phones; // <------- 我们关注这部分
@ElementCollection
@CollectionTable(name = "Websites", joinColumns = @JoinColumn(name = "myEntityId"))
@Column(name = "websites")
private List<String> websites; // <------- 我们关注这部分
@Fetch(FetchMode.SUBSELECT)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "myEntity")
private List<ContactEntity> bbb;
@Fetch(FetchMode.SUBSELECT)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "myEntity")
private List<AddressEntity> ccc;
}
这是我如何使用数据访问层(DAL)来获取它的方法:
List<MyEntity> findByTenantIdAndIdIn(String someOtherId, Set<String> MyEntityIds);
现在,当我迭代List<MyEntity>
来映射它,并调用myEntity.getPhones()
时,我看到正在进行数据库调用,这就是导致减速的原因,在1000个实体上减速了70秒。
那么,我该如何强制它在首次调用findByTenantIdAndIdIn
时执行join
操作,就像调用时所做的那样?
注:
Phones
是一个简单的表,具有列:[myEntityId, phone]Websites
也存在相同的问题。
英文:
I have major performance issues when I try to map an entity into a response.
This is the entity:
@Entity
@Table(name = "MyEntity")
public class MyEntity extends BaseEntity {
@Column(name = "someOtherId", nullable = false)
private String someOtherId;
@ElementCollection
@CollectionTable(name = "Phones", joinColumns = @JoinColumn(name = "myEntityId"))
@Column(name = "phone")
private List<String> phones; // <------- we care about this
@ElementCollection
@CollectionTable(name = "Websites", joinColumns = @JoinColumn(name = "myEntityId"))
@Column(name = "websites")
private List<String> websites; // <------- we care about this
@Fetch(FetchMode.SUBSELECT)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "myEntity")
private List<ContactEntity> bbb;
@Fetch(FetchMode.SUBSELECT)
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "myEntity")
private List<AddressEntity> ccc;
}
This is how I use the DAL to fetch it:
List<MyEntity> findByTenantIdAndIdIn(String someOtherId, Set<String> MyEntityIds);
Now when I iterate over List<MyEntity>
to map it, and call myEntity.getPhones()
, I see that a DB call is being made, which is what causes the slowdown, a 70 seconds slowdown on 1000 entities.
So what can I do to force it to join
in the first query it did when I called findByTenantIdAndIdIn
?
Notes:
Phones
is a simple table with columns: [myEntityId, phone]- The same problem happens with
Websites
答案1
得分: 1
这与它是一个 @ElementCollection
无关。就像你已经找出的那样,你可以使用子选择抓取,或者还可以使用批量大小来进行选择抓取(默认策略)。另一种可能性是在查询中使用fetch join,但要小心在fetch join多个集合时,这可能会创建一个笛卡尔积,导致性能问题,因为传输的行数太多。一个fetch join示例HQL查询如下:
SELECT e FROM MyEntity e LEFT JOIN FETCH e.phones LEFT JOIN FETCH e.websites
英文:
This has nothing to do with it being an @ElementCollection
. Like you figured out, you can use subselect fetching or could also use a batch size for select fetching(the default strategy). Another possibility is to use a fetch join in the query, but be careful when fetch joining multiple collections as that might create a cartesian product which leads to a performance problem cause by too many rows being transfered. A fetch join example HQL query looks like this:
SELECT e FROM MyEntity e LEFT JOIN FETCH e.phones LEFT JOIN FETCH e.websites
答案2
得分: 0
我发帖后立即解决了这个问题。
我使用@Fetch(FetchMode.SUBSELECT)
为电话和网站添加了注释,这会创建一个并行子查询。
解决这个问题的另一种方法是不使用@ElementCollection
,因为它性能较差,而是像他们在这个视频中推荐的那样,使用实体(Entity):https://thorben-janssen.com/hibernate-tips-query-elementcollection/。
英文:
I solved it right after I posted this.
I annotated phones and websites with @Fetch(FetchMode.SUBSELECT)
which creates a parallel subquery.
Another way to solve this is simply to not use @ElementCollection
because it has bad performance, use an Entity instead as they recommend in the video here: https://thorben-janssen.com/hibernate-tips-query-elementcollection/
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论