java OpenJPA criteriaBuilder 嵌套对象属性获取

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6396877/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 15:44:14  来源:igfitidea点击:

OpenJPA criteriaBuilder nested object property fetch

javacriteria-apiopenjpa

提问by quantum

Is there any way in OpenJPA to get hold of a nested object property via CriteriaBuilder?

OpenJPA 中是否有任何方法可以通过 CriteriaBuilder 获取嵌套对象属性?

Here's a small case.

这是一个小案例。

@Entity
public class X {
       private Object Y;

       // getters, setters...
}

@Entity
public class Y {
       private String Z;

       // getters, setters...
}

So, when using CriteriaBuilder, we use X as Root, i.e.:

因此,在使用 CriteriaBuilder 时,我们使用 X 作为 Root,即:

@PersistenceContext
private EntityManager entityManager;

//.....

Root<X> rootObj = criteriaBuilder.from(X.class);
CriteriaQuery<X> select;

String param1 = X.getY().getZ();

// initializing predicate, default value is TRUE
Predicate predicate1 = criteriaBuilder.isNull(null);

// construct search predicate which fails miserably due to IllegalArgumentExecption
if (X != null) {
predicate1 = criteriaBuilder.and(predicate1, criteriaBuilder.equal(rootObj.<String> get("Y.Z"), param1));}

Now, my grief is this -> get("Y.Z")

现在,我的悲伤是这样 -> get("Y.Z")

CriteriaBuilder doesn't know to fetch Z reflectively (however it can and will resolve Y). Is there any way to get hold of Z directly from get()?

CriteriaBuilder 不知道反射性地获取 Z(但是它可以并且将会解析 Y)。有什么办法可以直接从 get() 获取 Z 吗?

Apart from using JPQL, I can think of one other method - which I dislike immensely: I suppose I could have exposed Z as an @Transientproperty in X (as to prevent OpenJPA from persisting it as a column), but that sounds like a Really Bad Idea: I am essentially flattening out an object graph manually and introduce unneeded garbage inside the entity bean, not counting the time needed to flatten out a complex graph or the error-proness of this (it can go awry in so many ways).

除了使用 JPQL,我还能想到另一种方法——我非常不喜欢它:我想我可以将 Z 作为@TransientX 中的一个属性公开(以防止 OpenJPA 将它作为列持久化),但这听起来真的很糟糕想法:我基本上是手动展平对象图并在实体 bean 中引入不需要的垃圾,不计算展平复杂图所需的时间或容易出错的情况(它可能在很多方面出错)。

Is there a way to make this work? Any ideas are appreciated.

有没有办法使这项工作?任何想法表示赞赏。

回答by quantum

Heh, the solution is suprisingly simple - and it looks really ugly, but it works.

嘿,解决方案出奇的简单——它看起来真的很丑,但它确实有效。

predicate1 = criteriaBuilder.and(predicate1, criteriaBuilder.equal(rootObj.get("Y").<String> get("Z"), param1));}

I really don't know if there is a more elegant solution to this.

我真的不知道是否有更优雅的解决方案。

回答by Oleg Mikhailov

For any arbitrary nested attribute path ("relation.subRelation.attribute"):

对于任意嵌套的属性路径(“relation.subRelation.attribute”):

private Path<T> getPath(Root<T> root, String attributeName) {
    Path<T> path = root;
    for (String part : attributeName.split("\.")) {
        path = path.get(part);
    }
    return path;
}