OpenJPA criteriaBuilder嵌套对象属性获取

qua*_*tum 17 java openjpa criteria-api

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

这是一个小案例.

@Entity
public class X {
       private Object Y;

       // getters, setters...
}

@Entity
public class Y {
       private String Z;

       // getters, setters...
}
Run Code Online (Sandbox Code Playgroud)

因此,在使用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));}
Run Code Online (Sandbox Code Playgroud)

现在,我的悲痛就是 - > get("Y.Z")

CriteriaBuilder不知道反射取Z(但它可以并将解析Y).有没有办法直接从get()获取Z?

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

有没有办法让这项工作?任何想法都表示赞赏.

qua*_*tum 15

嘿,这个解决方案非常简单 - 它看起来很丑陋,但它确实有效.

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

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

  • 如果你使用元模型:`predicate1 = criteriaBuilder.and(predicate1,criteriaBuilder.equal(rootObj.get(X_.Y).get(Y_.Z),param1));}` (4认同)
  • 这是一个 [gist](https://gist.github.com/ulisseslima/7ff9d4ecc49470ccf5c5979b8d806eef) 用于处理带有简单字符串的子路径的基本 JPA 存储库。 (2认同)

Ole*_*lov 10

对于任意嵌套的属性路径(“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;
}
Run Code Online (Sandbox Code Playgroud)