Spring Data JPA中@Query传多元素List参数触发antlr语法异常
I’ve run into this exact gotcha with older Spring Boot versions—let’s break down why your query is failing and how to fix it quickly.
Why the Exception Occurs
When you pass a List<String> with multiple elements as docTypes, Hibernate expands the :docTypes parameter into a comma-separated list of individual parameters (like :docTypes_0_, :docTypes_1_). Your original condition (:docTypes is null or d.documentTypeName in :docTypes) gets transformed into invalid HQL:
(:docTypes_0_, :docTypes_1_ is null or d.documentTypeName in (:docTypes_0_, :docTypes_1_))
This syntax is broken because you can’t check if a collection of parameters is null—hence the unexpected AST node: {vector} error.
Solution for Spring Boot 1.5.x
Since you’re on Spring Boot 1.5.9, we can use Spring Expression Language (SpEL) directly in the @Query to safely check if the list is null or empty. Here’s the adjusted working query:
@Query(value = "select distinct d.documentId " + "from TrainingDocument d " + "where (:#{#docTypes == null or #docTypes.isEmpty()} or d.documentTypeName in :docTypes)") List<String> findDocByDocTypes(@Param("docTypes") List<String> docTypes);
How This Fix Works
- The SpEL expression
:#{#docTypes == null or #docTypes.isEmpty()}evaluates on the Java side before HQL parsing:- If
docTypesis null or empty, this condition resolves totrue, so the query returns all distinctdocumentIdvalues. - If
docTypeshas one or more elements, the condition resolves tofalse, and the query uses thein :docTypesclause as expected—no parameter expansion breaks the syntax.
- If
Verify All Scenarios
This fix covers all your use cases:
docTypes = null: Returns all distinct document IDsdocTypes = Collections.singletonList("PDF"): Filters for documents with type "PDF"docTypes = Arrays.asList("PDF", "DOCX"): Filters for documents with types "PDF" or "DOCX"
Alternative: Dynamic Criteria Query
If you prefer avoiding SpEL, build the query dynamically with the JPA Criteria API. This approach only adds the in clause when docTypes is valid:
@Autowired private EntityManager entityManager; public List<String> findDocByDocTypes(List<String> docTypes) { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQuery<String> query = cb.createQuery(String.class); Root<TrainingDocument> root = query.from(TrainingDocument.class); query.select(root.get("documentId")).distinct(true); if (docTypes != null && !docTypes.isEmpty()) { query.where(root.get("documentTypeName").in(docTypes)); } return entityManager.createQuery(query).getResultList(); }
内容的提问来源于stack exchange,提问作者Elina Zarisheva

