从表中选择所有类型的实体,但仅限于派生实体的成员
Posted
技术标签:
【中文标题】从表中选择所有类型的实体,但仅限于派生实体的成员【英文标题】:Selecting all kind of entities from a table but limiting to a member of a derived entity 【发布时间】:2013-08-14 11:31:16 【问题描述】:我有一个这样的实体结构:
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="CLASS_TYPE", discriminatorType= DiscriminatorType.STRING)
@DiscriminatorValue(value="SUPER")
public class SuperEntity implements Serializable
private String anyBaseMember;
... blah blah
@Entity
@DiscriminatorValue(value="DERIVED")
public class DerivedEntity extends SuperEntity
private String restrictingMember;
... getter / setter / blah blah
现在的中间目标是选择表的所有记录,而不管类类型如何,即我必须选择所有 SuperEntity 类,但带有 where 子句:
CriteriaQuery<SuperEntity> query = criteriaBuilder.createQuery(SuperEntity.class);
Root root = query.from(SuperEntity.class);
query.where(criteriaBuilder.equal(root.get(SuperEntity_.anyBaseMember), "BLAHBLAHBLAH"));
现在,这工作得很好,可以提供各种实体,SuperEntity 和 DerivedEntity,并受到该特定基本成员的限制。现在这是有趣的开始:当且仅当当前记录属于派生类的那种类型时,我必须对派生类的限制成员做进一步的限制。 这是我尝试过的:
Root root = query.from(SuperEntity.class);
query.where(criteriaBuilder.and(
criteriaBuilder.equal(root.get(SuperEntity_.anyBaseMember), "BLAHBLAHBLAH"),
criteriaBuilder.or(
criteriaBuilder.notEqual(root.type(), DerivedClass.class),
criteriaBuilder.equal(((Path) root.as(DerivedClass.class)).get(DerivedClass_.restrictingMember), "SNAFU")
)
));
长话短说:行不通:
Exception Description: Invalid query key [restrictingMember] in expression.
它不起作用,因为似乎不可能将根转换为任何其他类。至少它不适用于 .as()
我目前完成工作的方法是仅限制 SuperClass 的所有成员,然后在 for 循环中过滤掉所有其他限制。不是最先进的,而是我目前唯一的想法。
编辑:找到解决方案!
Root rootBase = query.from(SuperEntity.class);
Root rootDerived = query.from(DerivedClass.class);
query.where(criteriaBuilder.and(
criteriaBuilder.equal(rootBase, rootDerived),
criteriaBuilder.equal(rootBase.get(SuperEntity_.anyBaseMember), "BLAHBLAHBLAH"),
criteriaBuilder.or(
criteriaBuilder.notEqual(rootBase.type(), DerivedClass.class),
criteriaBuilder.equal(rootDerived.get(DerivedClass_.restrictingMember), "SNAFU")
)
));
非常感谢您的想法。 拉尔夫
【问题讨论】:
您是否尝试过使用单独的“derivedRoot”获取所需的表达式?像cb.equal(query.from(DerivedClass.class).get(DerivedClass_.restrictingMember), "SNAFU")
这样的东西?这只是在黑暗中的一个镜头,但首先想到的是,因为Root#as()
明确表示它不会改变运行时类型,并警告如果你将它用于不适合的用途,则会引发运行时异常。
您好,使用非连接的“from”会导致笛卡尔合并,即您将表的行数乘以自身。
【参考方案1】:
我知道您可以使用“类”属性查询命名查询中的鉴别器值,例如在select e from SuperEntity e where e.class ='DERIVED'
中。我知道它没有使用标准,但也许它可以提供帮助。
【讨论】:
这就是 .type() 的用途,而且效果很好。问题是访问派生类的成员字段。以上是关于从表中选择所有类型的实体,但仅限于派生实体的成员的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL ,从 2 个表中选择,但仅从表 2 中选择最新的元素
拥有所有实体派生自的 BaseEntity 类型或接口会更好吗?