从表中选择所有类型的实体,但仅限于派生实体的成员

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() 的用途,而且效果很好。问题是访问派生类的成员字段。

以上是关于从表中选择所有类型的实体,但仅限于派生实体的成员的主要内容,如果未能解决你的问题,请参考以下文章

如何阻止 eclipse 从表中自动创建 JPA 实体?

PostgreSQL ,从 2 个表中选择,但仅从表 2 中选择最新的元素

拥有所有实体派生自的 BaseEntity 类型或接口会更好吗?

如何从表中提取上下文数据来训练自定义命名实体识别器?

如何在实体框架中的两个表之间进行左连接操作时从左表中选择唯一行

用于从连接表中进行选择的 T-SQL 查询,其中有可变数量的参数?