如何创建“实例” -类似 JPA 2.0 中的查询吗?

发布于 2024-12-10 10:35:55 字数 295 浏览 0 评论 0原文

假设我们有一个抽象的 @Entity Animal,以及几个扩展 Animal 的实体类,包括 Dog、Cat、Monkey 和 Bat。

如何根据扩展实体的类过滤结果?

示例: 用户可以通过复选框选择要检索的实体。

[ ] Dog
[X] Cat
[X] Monkey
[ ] Bat

现在我想使用 Animal 类中定义的(命名)查询来检索实体。我可以在查询中放入什么样的查询参数,以便只返回 Cat 和 Monkey 对象?

Say we've got an abstract @Entity Animal, and several entity classes that extend Animal, including Dog, Cat, Monkey and Bat.

How can I filter the results based on the extending entity's class?

Example:
There are checkboxes where the user can select which entities to retrieve.

[ ] Dog
[X] Cat
[X] Monkey
[ ] Bat

Now I want to retrieve the entities with a (Named)Query defined in the Animal class. What kind of query parameters can I put into the query so that only the Cat and Monkey objects will be returned?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青萝楚歌 2024-12-17 10:35:55

我不确定它是否受 JPA 支持,但是在 Hibernate 中执行此操作的方法,无论继承策略如何,因此即使您没有鉴别器(或没有将其映射为属性)也是如此使用隐式 class 属性:

String jpql = "select a from Animal a where a.class in (:classes)";
Query q = em.createQuery(jpql).setParameter("classes", 
                                            Arrays.asList(Cat.class, Monkey.class));

编辑:

我刚刚发现在 JPA2 中可以使用 TYPE 运算符:

String jpql = "SELECT a FROM Animal a WHERE TYPE(a) IN :classes";
Query q = em.createQuery(jpql).setParameter("classes", 
                                            Arrays.asList(Cat.class, Monkey.class));

I'm not absolutely sure it's supported by JPA, but the way to do it in Hibernate, regardless of the inheritance strategy, and thus even if you don't have a discriminator (or didn't map it as a property) is to use the implicit class property :

String jpql = "select a from Animal a where a.class in (:classes)";
Query q = em.createQuery(jpql).setParameter("classes", 
                                            Arrays.asList(Cat.class, Monkey.class));

EDIT :

I just found it's possible in JPA2 using the TYPE operator :

String jpql = "SELECT a FROM Animal a WHERE TYPE(a) IN :classes";
Query q = em.createQuery(jpql).setParameter("classes", 
                                            Arrays.asList(Cat.class, Monkey.class));
与他有关 2024-12-17 10:35:55

您可以使用鉴别器列和值来仅搜索给定类型的某些子类型。默认情况下,鉴别器列的名称是 JPA 中的 DTYPE,类型是 String,值是类的名称。不过,您可以通过添加类级别注释 @DiscriminatorColumn(name="KIND", discriminatorType=DiscriminatorType.INTEGER) (用于鉴别器列的名称和类型)和 @DiscriminatorValue(" 来覆盖此设置1")(针对某个类别的特定鉴别器值)。然后,您可以在 yoru JPQL 查询的 WHERE 子句中使用它来仅获取某些子类型,例如:WHERE DTYPE="Dog" OR DTYPE="Cat"

You can use the discrimnator column and value to only search for certain subtypes of a given type. By default the discriminator column's name is DTYPE in JPA,the type is String and the value is the name of the class. You can however override this by adding the class level annotation @DiscriminatorColumn(name="KIND", discriminatorType=DiscriminatorType.INTEGER) (for the discriminator column's name and type) and @DiscriminatorValue("1") (for the specific discrimiminator value for a certain class). You can then use this in the WHERE clause of yoru JPQL query to only fetch certain subtypes, like: WHERE DTYPE="Dog" OR DTYPE="Cat"

柳絮泡泡 2024-12-17 10:35:55

这是我使用的:

    /**
     * Build an "instanceof" {@link Predicate} for an entity type.
     */
    @SuppressWarnings("unchecked")
    public static Predicate instanceOf(EntityManager entityManager, Path<?> path, Class<?> type) {
        Preconditions.checkArgument(entityManager != null, "null entityManager");
        Preconditions.checkArgument(path != null, "null path");
        Preconditions.checkArgument(type != null, "null type");
        final Set<Class<?>> subtypes = entityManager.getMetamodel().getManagedTypes().stream()
          .map(ManagedType::getJavaType)
          .filter(type::isAssignableFrom)
          .collect(Collectors.toSet());
        return JPAUtil.in(entityManager.getCriteriaBuilder(), (Expression<Class<?>>)path.type(), subtypes);
    }

    /**
     * Build an IN predicate from a collection of possible values.
     */
    public static <T> Predicate in(CriteriaBuilder builder, Expression<T> expr, Iterable<? extends T> values) {
        Preconditions.checkArgument(builder != null, "null builder");
        Preconditions.checkArgument(expr != null, "null expr");
        Preconditions.checkArgument(values != null, "null values");
        final CriteriaBuilder.In<T> in = builder.in(expr);
        values.forEach(in::value);
        return in;
    }

Here's what I use:

    /**
     * Build an "instanceof" {@link Predicate} for an entity type.
     */
    @SuppressWarnings("unchecked")
    public static Predicate instanceOf(EntityManager entityManager, Path<?> path, Class<?> type) {
        Preconditions.checkArgument(entityManager != null, "null entityManager");
        Preconditions.checkArgument(path != null, "null path");
        Preconditions.checkArgument(type != null, "null type");
        final Set<Class<?>> subtypes = entityManager.getMetamodel().getManagedTypes().stream()
          .map(ManagedType::getJavaType)
          .filter(type::isAssignableFrom)
          .collect(Collectors.toSet());
        return JPAUtil.in(entityManager.getCriteriaBuilder(), (Expression<Class<?>>)path.type(), subtypes);
    }

    /**
     * Build an IN predicate from a collection of possible values.
     */
    public static <T> Predicate in(CriteriaBuilder builder, Expression<T> expr, Iterable<? extends T> values) {
        Preconditions.checkArgument(builder != null, "null builder");
        Preconditions.checkArgument(expr != null, "null expr");
        Preconditions.checkArgument(values != null, "null values");
        final CriteriaBuilder.In<T> in = builder.in(expr);
        values.forEach(in::value);
        return in;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文