【发布时间】:2016-03-24 11:24:11
【问题描述】:
我正在使用 Spring 数据规范来编写使用 JPA 条件 API 的条件查询。
我有一个名为Thing 的类,它有一个Set<Characteristic> 属性。Characteristic 类是一个abstract 类,它有一个id 和一些共享的基本属性。
然后我有几个扩展Characteristic 并定义value 属性的具体类。
-
IntegerCharacteristic其中value属性是Integer -
DecimalCharacteristic其中value属性是Double -
StringCharacteristic其中value属性是String -
BooleanCharacteristic其中value属性是Boolean
每个Thing 在他的characteristics 集合中可以有0 个或多个Characteristic 的任何具体类型。
在数据库中,类层次结构是使用联合继承策略存储的(5 个表):
- 特征(id + 一些常用字段)
- integer_characteristic(外键 + INT 值)
- decimal_characteristic(外键 + DECIMAL 值)
- string_characteristic(外键 + VARCHAR 值)
- boolean_characteristic(外键 + TINYINT 值)
我需要使用 JPA 标准 API 来搜索至少具有指定值的特征的所有事物。
我已经编写了一个 SQL 查询草稿,我想用 JPA 标准 API 重现它:
SELECT DISTINCT thing.id
FROM thing
LEFT OUTER JOIN thing_has_characteristic has_c
ON ( has_c.thing_id = thing.id )
LEFT OUTER JOIN characteristic c
ON ( c.id = has_c.characteristic_id )
LEFT OUTER JOIN integer_characteristic integer_c
ON ( integer_c.characteristic_id = c.id )
LEFT OUTER JOIN string_characteristic string_c
ON ( string_c.characteristic_id = c.id )
LEFT OUTER JOIN boolean_characteristic boolean_c
ON ( boolean_c.characteristic_id = c.id )
LEFT OUTER JOIN decimal_characteristic decimal_c
ON ( decimal_c.characteristic_id = c.id )
WHERE integer_c.value = "9694"
OR string_c.value = "9694"
OR decimal_c.value = "9694"
OR boolean_c.value = "9694";
在尝试将其转换为 JPA 标准时,我遇到了困难,因为我认为我需要从一组 Characteristic 中构建一个子查询,以区分我拥有的四种 Characteristic 类。
现在,我尝试了一个只有 Integer 和 String 类型的小查询,但我对如何使其与 Characteristic 的子类层次结构一起工作感到困惑。
private Specification<Thing> buildSearchSpecificationByCharacteristicValue(String value) {
return (Specification<Thing>) (root, query, builder) -> {
SetJoin<Thing,IntegerCharacteristic> integers = root.<Thing,IntegerCharacteristic>joinSet("characteristics", JoinType.LEFT );
Predicate isInteger;
try{
isInteger = builder.equal(integers.get("value"), Integer.parseInt(value));
}catch(NumberFormatException e){
isInteger = builder.disjunction();
}
SetJoin<Thing,StringCharacteristic> strings = root.<Thing,StringCharacteristic>joinSet("characteristics", JoinType.LEFT);
Predicate isString = builder.equal(strings.get("value"), value);
return builder.or(
isInteger,
isString
);
};
}
它会产生以下错误:
org.springframework.dao.InvalidDataAccessApiUsageException:
Unable to locate Attribute with the the given name [value] on this
ManagedType [com.xxxxxxxx.common.domain.DomainObject];
nested exception is java.lang.IllegalArgumentException:
Unable to locate Attribute with the the given name [value]
on this ManagedType [com.xxxxxxxx.common.domain.DomainObject]
【问题讨论】:
标签: jpa inheritance collections spring-data criteria