简体   繁体   中英

How to write "JPQL" query with "IN" between SELECTs?

I wrote this JPQL query and expect a result as List<Question> :

@Query("SELECT q FROM Question q WHERE q.id IN (SELECT qc.questions FROM QCard qc WHERE qc.id IN (SELECT ct.qCards FROM CTest ct WHERE ct.id=:id))")

These are my classes:

class CTest {
  id List<QCard>
}

class QCard{
  id List<Question>
}

class Question{
  id
}

I expected all questions as return for given CTest.id . But I got a compiler-error with message:

SQLSyntaxErrorException

I tried use ":" before "select" words but it had not helped.

What is wrong?

List<Question> findByIdIn(List<Long> idList); //In repository

or

String qlString = "select i from Item i where i.name IN :names"; 
Query q = em.createQuery(qlString, Item.class);
List<String> names = Arrays.asList("foo", "bar");
q.setParameter("names", names);
List<Item> actual = q.getResultList();

I did those example in my past work, check it, tnx

In your existing query, in inner queries you are selecting entities and checking IN against Id, which will definitely won't work. As you can't complete entry with the Id.

As you haven't shared your complete entity structure, assuming that you have two way relationship declared correctly in entities, here I am placing a reference query which uses the join:

@Query("SELECT q FROM Question q JOIN q.qCard qc WHERE q.qCardId = qc.id AND qc.cTestId = :id")

Where qCardId is the foreign key reference of QCard entity in Question entity and cTestId is the foreign key reference of CTest entity in QCard entity.

You can use this for your reference to update your query with joins.

Test your SQL query in an SQL-client (eg Squirrel, DbVisualizer, etc.).

Assuming your foreign key s are named:

  • question_id in table QCard
  • card_id in table CTest

you could have an SQL with subselects like:

SELECT q.id
FROM Question q 
WHERE q.id IN (
  SELECT qc.question_id
  FROM QCard qc
  WHERE qc.id IN (
    SELECT ct.card_id
    FROM CTest ct
    WHERE ct.id = 1  -- example test id
  )
)

Does it return the expected result or are there syntax errors?

Then subsequently replace your subselects by JOIN s.

  1. Question and Cards
SELECT q.id, c.id
FROM Question q 
JOIN QCard c ON c.question_id = q.id
  1. Cards and Tests
SELECT c.id, t.id
FROM QCard c 
JOIN CTest t ON t.card_id = c.id
  1. All together
SELECT q.id, c.id, t.id
FROM Question q 
JOIN QCard c ON c.question_id = q.id
JOIN CTest t ON t.card_id = c.id

Note: add WHERE clauses like WHERE t.id = 1 if needed.

Experiment with the FROM/JOIN order as it makes sense.

Then translate the running SQL query to JPQL. For example:

@Query("SELECT q"
+ " FROM CTest test" 
// a test has many cards (1:n)
+ " JOIN QCard card ON card.id = test.card_id"  // associated cards
// a card has many questions (1:n)
+ " JOIN Question q ON q.id = card.question_id"  // associated questions
+ " WHERE test.id = :id")
public List<Question> findQuestionsByTestId(String id);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM