【问题标题】:JPA Criteria API join on 3 tables and some null elementsJPA Criteria API 加入 3 个表和一些空元素
【发布时间】:2020-06-16 08:32:38
【问题描述】:

我有一个父实体,它有两个子实体作为属性。 我想从父实体中选择具有给定参数作为个人属性的 childOne 或具有相同给定参数作为个人属性的 childTwo 的所有元素。

这是我简化的三个类:

父对象:

@Entity
public class ParentObject {

    @Id
    private int id;

    private int fkChildOne;

    private int fkChildTwo;

    @ManyToOne
    @JoinColumn(name = "fk_child_one_id", referencedColumnName = 
    "child_one_id")
    private ChildOne childOne;

    @ManyToOne
    @JoinColumn(name = "fk_child_one_id", referencedColumnName = 
    "child_one_id")
    private ChildTwo childTwo;

// getters and setters

}

子一对象:

@Entity 
public class ChildOne {

    @Id
    private int childOneId;

    private String nameChildOne;

    @OneToMany
    @JoinColumn(name = "fk_child_one_id")
    private List<ParentObject> parents;


// getters and setters

}

孩子两个对象:

@Entity
public class ChildTwo {

    @Id
    private int childOneId;

    private String nameChildTwo;

    @OneToMany
    @JoinColumn(name = "fk_child_two_id")
    private List<ParentObject> parents;


// getters and setters

}

规格类:

   public static Specification<ParentObject> checkName(String name) {

     return Specifications.where(
             (root, query, builder) -> {

                 final Join<ParentObject, ChildOne> joinchildOne = 
                 root.join("childOne");

                 final Join<ParentObject, ChildTwo > joinchildTwo = 
                 root.join("childTwo");

                 return builder.or(
                         builder.equal(joinchildOne .get("nameChildOne"), name),
                         builder.equal(joinchildTwo .get("nameChildTwo"), name)
                         );
             }
     );
    }

在我的服务中调用此规范时,我没有得到任何结果。但是,如果我在 builder.or 方法中注释掉两个连接之一和相应的谓词,那么我会得到一些结果,但它们显然与我正在寻找的不匹配,即选择具有带有该参数的 ChildOne 或带有该参数的 ChildTwo。

知道代码有什么问题吗?

【问题讨论】:

  • 你能把根实体、汽车实体和你执行提取的方法放在里面吗?
  • @JLazar0 我更新了我的帖子以更清晰。你能注意到问题吗?
  • 我看到的第一件事是孩子身上没有“@JoinColumn (name = "COLUMN")”注解。我也没有看到“@Id”注释。实体建模很重要,你是手动做的,你用eclipse吗?您正在研究数据模型吗?
  • @JLazar0 感谢您的回复。我已经用更好的代码更新了这篇文章,因为它确实不完整。我的 builder.or 方法仍然没有得到预期的结果。还有什么建议吗?

标签: jpa criteria-api


【解决方案1】:

终于找到了解决方案:要获取所有相应的结果,我必须添加将左连接的连接类型,因为我想获取所有 ParentObjects 而不管拥有 childOne 或 ChildTwo 对象。

final Join<ParentObject, ChildOne> joinchildOne = 
                 root.join("childOne", JoinType.LEFT);

                 final Join<ParentObject, ChildTwo > joinchildTwo = 
                 root.join("childTwo", JoinType.LEFT);

【讨论】:

  • 谢谢!我遇到了一个非常相似的问题。 Left Join 也是我的解决方案。
【解决方案2】:

太好了,现在你必须选择是否需要加入或获取。为了优化查询和内存,你应该将关系建立为 Lazy (@ManyToMany (fetch = FetchType.LAZY)),所以你只会带您需要的对象。

主要区别在于 Join 在变量中定义了表的交叉并允许您使用它来提取 select 子句中的某些字段,例如,另一方面,fetch 使其提供该变量的所有对象财产。在你的例子中, 从父节点中选择子节点(一旦关系设置为惰性)只会带来父类型的初始化对象,但是如果您执行提取,它将初始化父对象和子对象。

我要做的另一个修改是将标识符的类型更改为非原始类型,以便它接受空值,这是使用序列插入所必需的

【讨论】:

    猜你喜欢
    • 2015-05-30
    • 1970-01-01
    • 2015-02-15
    • 2016-12-20
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    相关资源
    最近更新 更多