Usage
Raw SQL
All query methods use ? placeholders for parameters. When a parameter is a Collection or array, it is
automatically expanded (e.g., WHERE id IN ? with a list of 3 becomes WHERE id IN (?, ?, ?)).
Use executeUpdate for INSERT, UPDATE, DELETE, or DDL statements:
For raw SELECT queries, use read, readOne, or readCursor described below.
Reading Data
Read a List
Returns all matching rows as a list:
Read a Single Row
Returns one result or null. Throws QueryException if multiple rows are found:
Cursor-Based Reading
For large result sets, use readCursor to process rows one at a time without loading them all into memory:
Reading by Multiple IDs
Pass a Collection or array as a parameter — the ? placeholder is expanded automatically:
Convenience Query Methods
findAll and findById provide shortcuts for common queries:
Populating Entities
If you have an entity with only its primary key set, you can load its remaining fields from the database:
Note: For AutoTable entities, populate() detaches the entity from any sibling batch group and loads it
individually. See AutoTable for details on batch loading.
CRUD Operations
Single Entity
Batch Operations
All CRUD methods accept collections for batch processing. Batch operations use JDBC batching for better performance.
Note on batch insert with auto-generated keys: When inserting multiple entities without pre-assigned IDs,
the generated keys will not be populated back to the entities (JDBC does not guarantee key ordering for batch
inserts). To reliably get generated IDs in batch inserts, use database sequences configured via
@DbField(primarySequence = "seq_name"), which are fetched in bulk before the insert.
Transaction Management
All operations inside a transaction share a single connection. If the block completes successfully, the transaction is committed. If an exception is thrown, the transaction is rolled back.
Basic Transaction
Nested Transactions
Nested calls to transaction() use database savepoints. If an inner transaction fails, only the inner transaction is
rolled back to its savepoint; the outer transaction can continue.
stormify().transaction(() -> {
stormify().create(record1);
try {
stormify().transaction(() -> {
stormify().create(record2); // If this fails...
});
} catch (QueryException e) {
// ...only record2 is rolled back. record1 is still pending.
}
});
// record1 is committed here.
Parent-Child Relationships
Use getDetails to retrieve child records of a parent entity:
The parent class must have exactly one primary key. If propertyName is not specified, Stormify finds the field
in the details class whose type matches the parent class. If multiple fields match, or none matches, a
QueryException is thrown.