0

架构:(伪代码)

我有一个名为 BaseEntity 的 bean ......

@Entity
class BaseEntity {
   @OneToMany @CascadeType.ALL
   List [Property] properties;
   //the use angled braces ommited for the stackoverflow editor to show up properly
}

财产是另一种豆...

@Entity
class Property {
   @ManyToOne
   Category category;
   @OneToOne
   Value value;
}

Value 实际上是一个抽象类,具有 Inheritence.SingleTable 和 NumericalValue 和 DateValue 等子类,以及(在抽象 Value 类中)@ManyToOne BaseType 类型。

目标:

我正在尝试编写一个查询,该查询选择具有特定名称类别的属性的 BaseEntity 对象,并选择其中的几个,获取具有任何给定属性的对象并在不存在的字段中获取 null。

尝试:

select entity.id as id, foo as foo, bar as bar 
from BaseEntity entity, Value foo, Value bar 
where foo in (select p.value from Property p where p in elements(entity.properties) and p.category.name = 'FOO') 
or bar in (select p.value from Property p where p in elements(entity.properties) and p.category.name = 'BAR')

此查询确实运行。目前,数据库中有一个 BaseEntity 匹配,我多次使用正确的 foo 结果得到它,它确实包含,但同样的实体一遍又一遍地在 bar 字段中有许多值。

此外,它需要大约五分钟的时间来运行并支持使用数据库的其他所有人。

想法:

当然,我考虑过只使用某种 distinct,但这并不能解决运行所需的极端时间,而且我只是不太明白发生了什么。

我希望你,我的同龄人,可以提出更好的查询方法。非常感谢!


我会发表评论,但是这段代码对于评论框来说太长了......我运行了一个查询,这个查询没有那么长以至于它挂起,但是任何更多的连接并且它确实挂起而不是完成......这个查询需要MINUTES 执行。

我从我的代码中运行了查询,并在休眠属性中打开了 show_sql。

select baseentity0_.entityId as col_0_0_, property2_.value_valueId as col_1_0_, property4_.value_valueId as col_2_0_, property6_.value_valueId as col_3_0_, property8_.value_valueId as col_4_0_, property10_.value_valueId as col_5_0_, value11_.valueId as valueId9_0_, value12_.valueId as valueId9_1_, value13_.valueId as valueId9_2_, value14_.valueId as valueId9_3_, value15_.valueId as valueId9_4_, value11_.type_typeId as type6_9_0_, value11_.numericalValue as numerica3_9_0_, value11_.textValue as textValue9_0_, value11_.dateValue as dateValue9_0_, value11_.value_entityId as value7_9_0_, value11_.DTYPE as DTYPE9_0_, value12_.type_typeId as type6_9_1_, value12_.numericalValue as numerica3_9_1_, value12_.textValue as textValue9_1_, value12_.dateValue as dateValue9_1_, value12_.value_entityId as value7_9_1_, value12_.DTYPE as DTYPE9_1_, value13_.type_typeId as type6_9_2_, value13_.numericalValue as numerica3_9_2_, value13_.textValue as textValue9_2_, value13_.dateValue as dateValue9_2_, value13_.value_entityId as value7_9_2_, value13_.DTYPE as DTYPE9_2_, value14_.type_typeId as type6_9_3_, value14_.numericalValue as numerica3_9_3_, value14_.textValue as textValue9_3_, value14_.dateValue as dateValue9_3_, value14_.value_entityId as value7_9_3_, value14_.DTYPE as DTYPE9_3_, value15_.type_typeId as type6_9_4_, value15_.numericalValue as numerica3_9_4_, value15_.textValue as textValue9_4_, value15_.dateValue as dateValue9_4_, value15_.value_entityId as value7_9_4_, value15_.DTYPE as DTYPE9_4_ from BaseEntity baseentity0_ inner join BaseEntity_Property properties1_ on baseentity0_.entityId=properties1_.BaseEntity_entityId inner join Property property2_ on properties1_.properties_propertyId=property2_.propertyId inner join Value value11_ on property2_.value_valueId=value11_.valueId inner join BaseEntity_Property properties3_ on baseentity0_.entityId=properties3_.BaseEntity_entityId inner join Property property4_ on properties3_.properties_propertyId=property4_.propertyId inner join Value value12_ on property4_.value_valueId=value12_.valueId inner join BaseEntity_Property properties5_ on baseentity0_.entityId=properties5_.BaseEntity_entityId inner join Property property6_ on properties5_.properties_propertyId=property6_.propertyId inner join Value value13_ on property6_.value_valueId=value13_.valueId inner join BaseEntity_Property properties7_ on baseentity0_.entityId=properties7_.BaseEntity_entityId inner join Property property8_ on properties7_.properties_propertyId=property8_.propertyId inner join Value value14_ on property8_.value_valueId=value14_.valueId inner join BaseEntity_Property properties9_ on baseentity0_.entityId=properties9_.BaseEntity_entityId inner join Property property10_ on properties9_.properties_propertyId=property10_.propertyId inner join Value value15_ on property10_.value_valueId=value15_.valueId, Category category16_, Category category17_, Category category18_, Category category19_, Category category20_ where property2_.category_categoryId=category16_.categoryId and property4_.category_categoryId=category17_.categoryId and property6_.category_categoryId=category18_.categoryId and property8_.category_categoryId=category19_.categoryId and property10_.category_categoryId=category20_.categoryId and category16_.name='Sample Name / Strain' and category17_.name='Item #' and category18_.name='THC_Result' and category19_.name='CBD_Result' and category20_.name='CBN_Result'


好吧,我想跟进并说,两个连接语句的出色工作与五个连接语句的工作缓慢可笑。

select entity.id as entityId, strain.value as name, item.value as itemNum, thc.value as THC, cbd.value as CBD, cbn.value as CBN

from BaseEntity as entity join entity.properties as strain join entity.properties as item join entity.properties as thc join entity.properties as cbd join entity.properties as cbn where strain.category.name = 'Sample Name / Strain' and item.category.name = 'Item #' and thc.category.name = 'THC_Result' and cbd.category.name = 'CBD_Result' and cbn.category.name = 'CBN_Result'

有什么更好的方法可以用我愚蠢的模式更快地做到这一点吗?

4

4 回答 4

1

性能问题看起来像是在您的子选择中。

稍微拆开会怎样

select entity from BaseEntity as entity join entity.properties as property where
property.category.name in ( 'FOO','BAR' )

这将为您提供具有 FOO 或 BAR 属性的基本实体列表,然后如果您想限制 baseEntity.properties 的集合,请使用过滤器或重新查询来获取属性。

from properity where  property.category.name in ( 'FOO', 'BAR' )
and property.baseEntity.priKey = :priKey 
于 2009-06-11T18:06:27.213 回答
0

您是否覆盖关联的默认提取类型?通常这会导致问题。您可以发布 Hibernate 生成的查询吗?

于 2009-06-11T17:18:09.157 回答
0

绝对是 ccclark 的回答让我找到了方向,我的好朋友也提供了帮助......

select entity.id as entityId, entity.type as entityType, p1.value as Vendor, p2.value as Weight 
from BaseEntity as entity 
join entity.properties as p1 
join entity.properties as p2 
where p1.category.name = 'Vendor' and p2.category.name = 'Total Weight'

正是我需要的。感谢 StackOverFlow 社区!

于 2009-06-11T19:05:54.340 回答
0

这个查询在我看来是合理的。所以问题是:

hibernate 为该 HQL 生成什么 SQL?

数据库为该 SQL 生成的查询计划是什么?

在 Sybase 或 MS SQL Server 中:“set showplan on”。在 Oracle 中,使用 SQLDeveloper/Toad 并选择计划/救护车。

您可能需要使用类别表中类别名称的索引,以及属性表中的类别 ID 和实体 ID 以及值表中的主键、值 ID 的索引。

于 2009-06-12T00:30:41.033 回答