英文:
Hibernate - joined strategy selects too many columns
问题
我们正在使用Hibernate 4.2.14,在JBoss EAP 6.3上,以及PostgreSQL 12。在我们的应用程序中,我们使用了“joined”继承策略。
问题出现在当我们查询超类时,Hibernate会尝试与继承的所有子类进行连接,并选择所有子类的所有列,从而触发了“目标列表最多可以有1664个条目”的Postgres错误。
使用鉴别器列是否可能是解决方案?在这种情况下,Hibernate将知道要查询哪个子类,并且应该仅与特定子类一起连接超类,从而避免导致错误的大型选择。这是否可能?我们有遗漏了什么吗?
英文:
We are using Hibernate 4.2.14 on JBoss eap 6.3, and PostgreSQL 12. On our app we are using "joined" inheritance strategy.
The problem appears when we query the superclass, then hibernate tries to join with all the subclasses of the inheritance and selects all the colums of all the subclasses, so then hits the "target lists can have at most 1664 entries" Postgres error.
Could using a discriminator column be the solution ? in that scenario hibernate will know which subclass to query and should join the superclass only with the specific subclass, avoiding the giant select which leads to error. is that possible ? are we missing something ?
答案1
得分: 1
在Hibernate 5.4中,针对这一点进行了优化,仅进行真正必要的联接,但仍可能出现这种情况,而且由于您似乎正在进行连接提取,更新操作不能使您摆脱这种情况。您将不得不为某些关联使用不同的提取策略,以减少联接和选择项的数量。有关更多信息,请参见:https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#fetching-fetch-annotation
如果您还想通过减少要选择的列数来进一步提高性能,您还可以重写查询,不使用实体的连接提取,而是仅选择实际需要的实体字段。这是Blaze-Persistence Entity Views的一个完美用例。
我创建了这个库,以便在JPA模型和自定义接口或抽象类定义的模型之间实现轻松映射,类似于功能强化版的Spring Data Projections。思路是您可以按照喜欢的方式定义目标结构(领域模型),并通过JPQL表达式将属性(getter)映射到实体模型。
针对您的用例,使用Blaze-Persistence Entity-Views的DTO模型可能如下所示:
@EntityView(A.class)
public interface ADto {
@IdMapping
Long getId();
String getName();
@Mapping("bCollection")
Set<BDto> getBs();
@EntityView(B.class)
interface BDto {
@IdMapping
Long getId();
String getName();
}
}
查询只需将实体视图应用于查询,最简单的方法只是根据ID查询。
ADto a = entityViewManager.find(entityManager, ADto.class, id);
Spring Data集成允许您几乎像使用Spring Data Projections一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Blaze-Persistence Entity-Views还支持提取策略的概念。
英文:
In Hibernate 5.4 this was optimized to only do joins that are really necessary, but there might still be situations how this can happen and I since you seem to be doing join fetches the update won't save you from this. You will have to use a different fetch strategy for some associations to reduce the amount of joins and select items. See here for more information: https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#fetching-fetch-annotation
If you also want to improve performance further by reducing the amount of columns to select, you could also rewrite queries to not use join fetching of entities but instead select only the entity fields you really need. This is a perfect use case for Blaze-Persistence Entity Views.
I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.
A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:
@EntityView(A.class)
public interface ADto {
@IdMapping
Long getId();
String getName();
@Mapping("bCollection")
Set<BDto> getBs();
@EntityView(B.class)
interface BDto {
@IdMapping
Long getId();
String getName();
}
}
Querying is a matter of applying the entity view to a query, the simplest being just a query by id.
ADto a = entityViewManager.find(entityManager, ADto.class, id);
The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Blaze-Persistence Entity-Views also supports the concept of fetch strategies
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论