SqlUpdate
SqlUpdate allows us to execute sql insert, sql update or sql delete statements.
Example: simple update
String sql = "update audit_log set description = description where id = ?";
int row = DB.sqlUpdate(sql)
.setParameter(1, 42)
.execute();
Example: insert with getGeneratedKeys
String sql = "insert into e_person_online (email, online_status, when_updated) " +
"values (:email, :online, current_time)";
SqlUpdate sqlUpdate = DB.sqlUpdate(sql)
.setGetGeneratedKeys(true)
.setParameter("email", email)
.setParameter("online", false);
sqlUpdate.execute();
Object key = sqlUpdate.getGeneratedKey();
Binding collections
To bind collections/arrays of values into an IN clause we need to use
indexed positioned parameters like ?1, ?2, ?3
etc or
named parameters like :ids, :names
etc.
// using ?1 index positioned parameter
String sql = "delete from customer where ref_id in (?1)";
int rows = DB.sqlUpdate(sql)
.setParameter(asList(9991, 9992, 9993))
.execute();
delete from customer where ref_id in (?,?,?)
// using :ids named parameter
String sql = "delete from customer where ref_id in (:ids)";
int rows = DB.sqlUpdate(sql)
.setParameter("ids", asList(9991, 9992, 9993))
.execute();
delete from customer where ref_id in (?,?,?)
Example: binding multiple lists
String sql = "delete from customer where ref_id in (:ids) and name in (:names)";
int rows = DB.sqlUpdate(sql)
.setParameter("ids", asList(9991, 9992, 9993))
.setParameter("names", asList("rob", "jim"))
.execute();
delete from customer where ref_id in (?,?,?) and name in (?,?)
CTE - Common table expression
When we want to perform a bulk update using a common table expression this is easiest done using SqlUpdate.
CTE Example
String sql = """
WITH t AS (
SELECT s.id AS _id
FROM store_price s
JOIN promotion_vw p ...
WHERE ...
)
UPDATE store_price
SET promotion_price = null, price = active_price, price_reason = ?,
version = version+1, when_modified = current_timestamp
FROM t
WHERE id = t._id
"""
int rows = DB.sqlUpdate(sql)
.setParameter(1, "Expired promotions")
.execute();
AddBatch and ExecuteBatch
We use addBatch() and executeBatch() to explicitly use JDBC batching.
String sql = "insert into audit_log (id, description, modified_description) values (?,?,?)";
SqlUpdate insert = DB.sqlUpdate(sql);
try (Transaction txn = DB.beginTransaction()) {
insert.setNextParameter(10000);
insert.setNextParameter("hello");
insert.setNextParameter("foo");
insert.addBatch();
insert.setNextParameter(10001);
insert.setNextParameter("goodbye");
insert.setNextParameter("bar");
insert.addBatch();
insert.setNextParameter(10002);
insert.setNextParameter("chow");
insert.setNextParameter("baz");
insert.addBatch();
int[] rows = insert.executeBatch();
txn.commit();
}
Upsert
We can execute upsert sql which is generally database specific.
Upsert - Postgres
String sql =
"insert into e_person_online (email, online_status, when_updated) values (?, ?, now()) " +
"on conflict (email) do update set when_updated=now(), online_status = ?";
String email = "foo@one.com";
Object key = DB.sqlUpdate(sql)
.setGetGeneratedKeys(true)
.setParameter(1, email)
.setParameter(2, true)
.setParameter(3, true)
.executeGetKey();
Upsert - MySql
String email = "bar@one.com";
String sql =
"insert into e_person_online (email, online_status, when_updated) values (?, ?, current_time) " +
"on duplicate key update when_updated=current_time, online_status = ?";
Object key = DB.sqlUpdate(sql)
.setGetGeneratedKeys(true)
.setParameter(1, email)
.setParameter(2, true)
.setParameter(3, true)
.executeGetKey();
L2 cache
If L2 caching is being used Ebean will by default automatically try and determine what table modifications are performed and use this to invalidate appropriate parts of the L2 cache.
Use setAutoTableMod(false)
to turn this off.