How to use a dynamic parameter in a IN clause of a JPA named query?
JPA support the use of a collection as a list literal parameter only in JPQL queries, not in native queries. Some JPA providers support it as a proprietary feature, but it's not part of the JPA specification (see https://stackoverflow.com/a/3145275/1285097).
Named parameters in native queries also aren't part of the JPA specification. Their behavior depends on the persistence provider and/or the JDBC driver.
Hibernate with the JDBC driver for Oracle support both of these features.
List<String> selectedValues = Arrays.asList("STRING1", "STRING2");
final String parameterizedQuery = "select * from SOMETABLE where SOMEFIELD in (:selectedValues)";
return em.createNativeQuery(parameterizedQuery)
.setParameter("selectedValues", selectedValues)
.getResultList();
JPA passing list to IN clause in named native query
A list is not a valid parameter for a native SQL query, as it cannot be bound in JDBC. You need to have a parameter for each argument in the list.
where u.user_id in (?id1, ?id2)
This is supported through JPQL, but not SQL, so you could use JPQL instead of a native query.
Some JPA providers may support this, so you may want to log a bug with your provider.
Named query with input parameter
In JPA 2.0 and below, parameters are not allowed in the set clause of a named query; only literals. This limitation is lifted if you are using JPA 2.1.
From what I can gather, you are not using JPA 2.1. Hence, I'll give you a couple of ways to sidestep this limitation.
Option 1:
Use the createQuery method and pass a dynamically generated string to the method.
String queryString = generateQueryString(email, username);
entityManager.createQuery(queryString).executeUpdate();
Option 2:
Update the associated entity and merge.
List<User> result = entityManager.createQuery('select u from user u where
u.username = :username').setParameter('username', username).getResultList();
for (User user : result) {
user.setEmail(email);
entityManager.merge(user);
}
Option 3:
Create the query using HQL not JPQL. I haven't tested this nor do I recommend it because you are going behind the entity manager's back.
Query q = sessionFactory.getCurrentSession().createNamedQuery('updateEmailAddress');
q.setParameter('email', email);
q.setParameter('username', username);
q.executeUpdate();
How to create a dynamic WHERE clause for all queries in Spring Data JPA?
Spring Data (I assume you are using Spring Data based on your post tags) doesn't support query augmentation (at time of writing). There is a long standing request for that feature here that also describes some alternatives that others have tried.
Good luck!
How to create a dynamic WHERE clause for a query using an array list
Either check if JDBC Template from Spring handle that for you using a syntax which could be something like (from the doc, I don't think it does)
SELECT question_id FROM question WHERE category in (?...)
Or write your own query with the problems that may arise:
List<Object> parameters = new ArrayList<>(categories.size());
StringBuilder sb = new StringBuilde("SELECT question_id FROM question WHERE 1=1");
if (!categories.isEmpty()) {
if (categories.size() == 1) {
sb.append(" and category = ?");
} else {
sb.append(" and category in ");
sb.append(categories.stream()
.map(ignored -> "?")
.collect(joining(", ", "(", ")")));
sb.append(")");
}
parameters.addAll(categories);
}
Object[] paramArray = parameters.toArray();
jdbcTemplate.query(sb.toString(), stringMapper, paramArray);
Notes:
- some security/quality tool may report SQL issues because you are writing a dynamic SQL.
- Oracle put a limit on 1000 elements per IN. You would have to partition categories per group of 1000 (or less).
- I used a
stream()
in a more or less strange fashion in order to generate the "?". If you use commons-lang3, you can replace it by"(" + StringUtils.repeat("?", ", ", categories.size()) + ")"
(the example in the javadoc was probably done with this kind of use). - if you only have category as single criteria, you may probably remove the
1=1
as well as theand
.
Related Topics
How to Return a Incremental Group Number Per Group in SQL
Redundant Data in Update Statements
How to Implement SQL Intersect and Minus Operations in Ms Access
The Network Adapter Could Not Establish the Connection - Oracle 11G
Oracle- Split String Comma Delimited (String Contains Spaces and Consecutive Commas)
Cumulative Total in Ms SQL Server
Convert a String to Int Using SQL Query
Do I Need to Create Indexes on Foreign Keys on Oracle
How to Find Unicode/Non-Ascii Characters in an Ntext Field in a SQL Server 2005 Table
Designing SQL Database to Represent Oo Class Hierarchy
Postgresql Join with Array Type with Array Elements Order, How to Implement
How to Generate Ranks in MySQL
How to Use a Dynamic Parameter in a in Clause of a JPA Named Query
SQL Server: Find Out Default Value of a Column with a Query
Faster Way to Insert, via Script, in Oracle
How to See the Structure of Mulitple Table with a Single "Desc"