JPA Criteria API объединяет 3 таблицы и некоторые нулевые элементы - PullRequest
0 голосов
/ 16 июня 2020

У меня есть одна родительская сущность, у которой есть две дочерние сущности в качестве атрибутов. Я хочу выбрать все элементы из родительской сущности, которые имеют ЛИБО 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)
                         );
             }
     );
    }

Когда этот сп c вызывается в моем сервисе, я не получаю результатов. Однако, если я закомментирую одно из двух объединений и соответствующий предикат в моем методе builder.or, то я получаю некоторые результаты, но они явно не соответствуют тому, что я ищу, а именно: выбрать каждый ParentObject, у которого есть либо ChildOne с этим параметром или ChildTwo с этим параметром.

Есть подсказка, что не так с кодом?

Ответы [ 2 ]

1 голос
/ 17 июня 2020
• 1000 *
0 голосов
/ 17 июня 2020

Отлично, теперь вам нужно выбрать, нужно ли вам присоединиться или извлечь. Чтобы оптимизировать запрос и память, вы должны sh установить отношения как Lazy (@ManyToMany (fetch = FetchType.LAZY)), поэтому вы принесет только те объекты, которые вам требуются.

Основное отличие состоит в том, что Join определяет пересечение таблиц в переменной и позволяет вам использовать его для извлечения определенных полей в предложении select, например, в с другой стороны, fetch заставляет его кормить все объекты этого свойства. В вашем примере выбор из родительского элемента с объединением дочерних элементов (если отношение установлено как ленивое) принесет только инициализированные объекты типа parent, однако, если вы выполните выборку, это приведет к инициализации родительского и дочернего объектов.

Еще одна модификация, которую я бы сделал, - это изменить тип идентификатора на непримитивный, чтобы он принимал нулевые значения, необходимые для вставки с использованием последовательностей

...