diff --git a/src/main/java/io/ebean/ExpressionList.java b/src/main/java/io/ebean/ExpressionList.java
index 5c7750cd3..2ac175d6a 100644
--- a/src/main/java/io/ebean/ExpressionList.java
+++ b/src/main/java/io/ebean/ExpressionList.java
@@ -1251,26 +1251,37 @@ public interface ExpressionList
- * The raw expression should contain a single ? at the location of the
- * parameter.
+ * The raw expression should contain a single ? or ?1
+ * at the location of the parameter. We use ?1 when binding a
+ * collection for an IN expression.
*
+ * >
* When properties in the clause are fully qualified as table-column names
* then they are not translated. logical property name names (not fully
* qualified) will still be translated to their physical name.
*
- *
- * The raw expression should contain the same number of ? as there are
- * parameters.
- *
* When properties in the clause are fully qualified as table-column names
* then they are not translated. logical property name names (not fully
* qualified) will still be translated to their physical name.
*
+ * When binding a collection of values into a IN expression we should use
+ * indexed parameters like ?1, ?2, ?3 etc rather than just ?.
+ *
+ * When binding a collection of values into a IN expression we should use
+ * indexed parameters like ?1, ?2, ?3 etc rather than just ?.
+ *
* Provides a simple way to execute raw SQL insert update or delete statements
* without having to resort to JDBC.
- *
* Supports the use of positioned or named parameters and can automatically
* notify Ebean of the table modified so that Ebean can maintain its cache.
- *
* Note that {@link #setAutoTableMod(boolean)} and
* Ebean#externalModification(String, boolean, boolean, boolean)} can be to
* notify Ebean of external changes and enable Ebean to maintain it's "L2"
* server cache.
- *
- * Example:
+ * Examples:
* {@code
*
* // use a database function
* raw("add_days(orderDate, 10) < ?", someDate)
*
+ * raw("name like ?", "Rob%")
+ *
+ * raw("name in (?1)", asList("Rob", "Fiona", "Jack"))
+ *
+ * raw("name = any(?)", asList("Rob", "Fiona", "Jack"))
+ *
* }
*
- * Subquery example:
+ * Subquery examples:
* {@code
*
+ * // Bind collection using ?1
+ * .raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack"))
+ *
+ * // Using Postgres ANY expression
* .raw("t0.customer_id in (select customer_id from customer_group where group_id = any(?::uuid[]))", groupIds)
*
* }
@@ -1280,14 +1291,25 @@ public interface ExpressionListExamples:
+ * {@code
+ *
+ * raw("unitPrice > ? and product.id > ?", 2, 3)
+ *
+ * raw("(status = ? or (orderDate < ? and shipDate is null) or customer.name like ?)",
+ * Order.Status.APPROVED,
+ * new Timestamp(System.currentTimeMillis()),
+ * "Rob")
+ *
+ * }
*/
ExpressionList{@code
+ *
+ * String sql = "select c.id, c.name from customer c where c.name in (?1)";
+ *
+ * List
+ *
* @param value The value to bind
*/
SqlQuery setParameter(Object value);
/**
* Bind the parameter by its index position (1 based like JDBC).
+ * {@code
+ *
+ * String sql = "select c.id, c.name from customer c where c.name in (?1)";
+ *
+ * List
*/
SqlQuery setParameter(int position, Object value);
diff --git a/src/main/java/io/ebean/SqlUpdate.java b/src/main/java/io/ebean/SqlUpdate.java
index 2669ed224..927050d3f 100644
--- a/src/main/java/io/ebean/SqlUpdate.java
+++ b/src/main/java/io/ebean/SqlUpdate.java
@@ -5,18 +5,16 @@ package io.ebean;
* Positioned parameter example
* {@code
*
* // example using 'positioned' parameters
@@ -30,6 +28,7 @@ package io.ebean;
*
* }
*
+ * Named parameter example
* {@code
*
* // example using 'named' parameters
@@ -45,8 +44,31 @@ package io.ebean;
* String msg = "There were " + rows + " rows updated";
*
* }
+ *
+ * Index parameter examples (e.g. ?1, ?2, ?3 ...)
* Example: Using setNextParameter()
+ * We can use index parameters like ?1, ?2, ?3 etc when binding arrays/collections
+ * of values into an IN expression.
+ *
{@code
+ *
+ * // Binding a list of 3 values (9991, 9992, 9993) into an IN expression
+ *
+ * DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)")
+ * .setParameter(1, "Foo")
+ * .setParameter(2, asList(9991, 9992, 9993))
+ * .execute();
+ *
+ * // note this effectively is the same as
+ *
+ * DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)")
+ * .setParameter("Foo")
+ * .setParameter(asList(9991, 9992, 9993))
+ * .execute();
+ *
+ * }
+ *
+ * {@code
*
* String sql = "insert into audit_log (id, description, modified_description) values (?,?,?)";
@@ -56,19 +78,19 @@ package io.ebean;
* try (Transaction txn = DB.beginTransaction()) {
* txn.setBatchMode(true);
*
- * insert.setNextParameter(10000);
- * insert.setNextParameter("hello");
- * insert.setNextParameter("rob");
+ * insert.setParameter(10000);
+ * insert.setParameter("hello");
+ * insert.setParameter("rob");
* insert.execute();
*
- * insert.setNextParameter(10001);
- * insert.setNextParameter("goodbye");
- * insert.setNextParameter("rob");
+ * insert.setParameter(10001);
+ * insert.setParameter("goodbye");
+ * insert.setParameter("rob");
* insert.execute();
*
- * insert.setNextParameter(10002);
- * insert.setNextParameter("chow");
- * insert.setNextParameter("bob");
+ * insert.setParameter(10002);
+ * insert.setParameter("chow");
+ * insert.setParameter("bob");
* insert.execute();
*
* txn.commit();
@@ -81,19 +103,19 @@ package io.ebean;
*
* try (Transaction txn = DB.beginTransaction()) {
*
- * insert.setNextParameter(10000);
- * insert.setNextParameter("hello");
- * insert.setNextParameter("rob");
+ * insert.setParameter(10000);
+ * insert.setParameter("hello");
+ * insert.setParameter("rob");
* insert.addBatch();
*
- * insert.setNextParameter(10001);
- * insert.setNextParameter("goodbye");
- * insert.setNextParameter("rob");
+ * insert.setParameter(10001);
+ * insert.setParameter("goodbye");
+ * insert.setParameter("rob");
* insert.addBatch();
*
- * insert.setNextParameter(10002);
- * insert.setNextParameter("chow");
- * insert.setNextParameter("bob");
+ * insert.setParameter(10002);
+ * insert.setParameter("chow");
+ * insert.setParameter("bob");
* insert.addBatch();
*
* int[] rows = insert.executeBatch();
diff --git a/src/test/java/org/tests/query/TestWhereRawClause.java b/src/test/java/org/tests/query/TestWhereRawClause.java
index 41ebfc6f2..f90360371 100644
--- a/src/test/java/org/tests/query/TestWhereRawClause.java
+++ b/src/test/java/org/tests/query/TestWhereRawClause.java
@@ -1,6 +1,7 @@
package org.tests.query;
import io.ebean.BaseTestCase;
+import io.ebean.DB;
import io.ebean.Ebean;
import io.ebean.Expr;
import io.ebean.Query;
@@ -57,7 +58,7 @@ public class TestWhereRawClause extends BaseTestCase {
ResetBasicData.reset();
- Query query = Ebean.find(Customer.class)
+ Query query = DB.find(Customer.class)
.where()
.raw("id in (select c.id from o_customer c where c.name in (?1))", asList("Rob", "Fiona", "Jack"))
.query();