JPA2 Критерий Запрос для выбора записей в таблице A, ссылка на которые не найдена в таблице B - PullRequest
0 голосов
/ 11 мая 2018

У меня есть следующие таблицы со следующей структурой

Table A {
    id <-- Primary key
    someColumn 
}

Table B {
    id <-- Primary key
    someColumn 
    idOfA <-- Foreign key mapping to Table A
}

Классы сущностей выглядят как показано ниже

@Entity
@Table(name = "A")
public class A implements Serializable {
    private static final long serialVersionUID = -78448557049178402L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    .......
    .......
    @OneToMany(mappedBy = "a")
    private List<B> bs = new ArrayList<>();
}

@Entity
@Table(name = "B")
public class B implements Serializable {
    private static final long serialVersionUID = -659500557015441771L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    .......
    .......
    @OneToOne
    @JoinColumn(name = "a_id", nullable = false)
    private A a;
 }

Используя JPA2, я хочу выбрать записи из таблицы A, которые не имеют ссылки в таблице B.

Ожидаемый собственный запрос postgres

select * from A a 
    where a.id not in 
        (select b.idOfA from B b);

Что мне до сих пор удавалось сделать, это

public List<A> getANotInB() {
    CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();


    // Select From Table B
    CriteriaQuery<B> criteriaQueryB = criteriaBuilder
            .createQuery(B.class);
    Root<B> rootB = criteriaQueryB.from(B.class);
    criteriaQueryB.select(rootB);

    // Select records from Table A
    CriteriaQuery<A> criteriaQueryA = criteriaBuilder.createQuery(A.class);
    Root<A> rootA = criteriaQueryA.from(A.class);
    criteriaQueryA.select(A);

    // Create predicate   
    Predicate predicate = rootAttemptA.in(criteriaQueryB.getSelection());
    criteriaQueryA.where(criteriaBuilder.not(predicate));

    // Create query

    TypedQuery<A> query = entityManager.createQuery(criteriaQueryA);
    List<A> as= query.getResultList();
    System.out.println(as);
    return as;
}

Я знаю, что приведенный выше код неверен, и у меня много основ вонг. Пожалуйста, помогите

Примечание: я хочу использовать JPA2 Criteria Query

Ответы [ 2 ]

0 голосов
/ 11 мая 2018

Мне удалось сделать это с помощью subquery (), как показано ниже. Размещать его так, чтобы он мог помочь другим

CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();

// select a from A a 
CriteriaQuery<A> queryA = criteriaBuilder.createQuery(A.class);
Root<A> rootA = queryA.from(A.class);
queryA.select(rootA);

// Select distinct aId from B
CriteriaQuery<B> subQueryB = queryA.subquery(B.class);
Root<B> rootB = subQueryB.from(B.class);
bQuery.select(rootB.get("a")).distinct(true);

queryA.where(criteriaBuilder.not(criteriaBuilder.in(rootA.get("id").value(subQueryB))));

TypedQuery<A> query = entityManager.createQuery(aQuery);
List<A> result = query.getResultList();

Спасибо @ Mạnh за то, что показали путь

0 голосов
/ 11 мая 2018

Попробуйте это

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();

    // Select distinct aid from B
    CriteriaQuery<B> bQuery = cb.createQuery(B.class);
    Root<B> bRoot = bQuery.from(B.class);
    bQuery.select(bRoot.get("a").get("id")).distinct(true);

    // Select * from A where aid not in ()
    CriteriaQuery<A> aQuery = cb.createQuery(A.class);
    Root<A> aRoot = aQuery.from(A.class);
    aQuery.select(aRoot).where(cb.not(aRoot.get("id").in(bQuery)));

    TypedQuery<A> query = entityManager.createQuery(aQuery);
    List<A> result = query.getResultList();

По сути, вы создадите часть запроса и склеите их вместе.

Более подробная информация здесь:

Критерии JPA

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...