✅ Advanced JDBC usage
Most application code should use @JdbcSelect, @JdbcUpdate, parameter
binding, and result mapping directly.
Use the advanced patterns on this page when you need batch execution or direct
access to the JDBC Connection.
Common Cases
Section titled “Common Cases”Insert many rows with a batch
Section titled “Insert many rows with a batch”Use @JdbcBatchUpdate when you want to collect many update calls and execute
them as JDBC batches.
The method returns an interface that extends JdbcBatch.
That batch interface contains exactly one @JdbcUpdate method.
interface CustomerBatch extends JdbcBatch { @JdbcUpdate("INSERT INTO db_customers (name, budge, pricing_plan) VALUES (:name, :budge, :plan)") void insertCustomer(String name, Integer budge, PricingPlan plan);}
enum PricingPlan { FREE, BASIC, PRO, ENTERPRISE}
@JdbcBatchUpdateCustomerBatch insertCustomers();Use the batch in a try-with-resources block.
The generated batch executes automatically when the batch size is reached and
again when the batch is closed.
@Testvoid insertCustomers() { try (var batch = service.insertCustomers()) { batch.insertCustomer("Alpha", 100, FREE); batch.insertCustomer("Bravo", 200, PRO); batch.executeBatch(); }
assertThat(service.customerNames()).containsExactly("Alpha", "Bravo");}Write a batch before it is full
Section titled “Write a batch before it is full”Call executeBatch() when you want to send the currently collected statements
before the configured batch size is reached.
The batch remains open and can collect more rows afterwards.
@Testvoid executeBatchBeforeItIsFull() { try (var batch = service.insertCustomersWithSize(10)) { batch.insertCustomer("Alpha", 100, FREE); batch.insertCustomer("Bravo", 200, PRO);
assertThat(service.customerNames()).isEmpty();
assertThat(batch.executeBatch()).containsExactly(1, 1); assertThat(service.customerNames()).containsExactly("Alpha", "Bravo"); }}Choose a batch size
Section titled “Choose a batch size”Use @JdbcBatchSize on the @JdbcBatchUpdate method for a fixed batch size.
Use @JdbcBatchSize on a method parameter when the caller should choose the
size.
@JdbcBatchSize(5)@JdbcBatchUpdateCustomerBatch insertCustomersInGroupsOfFive();
@JdbcBatchUpdateCustomerBatch insertCustomersWithSize(@JdbcBatchSize int batchSize);Use native JDBC for one method
Section titled “Use native JDBC for one method”Use @JdbcNative when a method needs direct JDBC access.
By default, Kaumei JDBC looks for a static method with the same name in
the same interface.
The static method receives the active Connection as its first parameter,
followed by the interface method parameters.
@JdbcNativeList<String> tableNames(String tableNamePattern);
static List<String> tableNames(Connection connection, String tableNamePattern) throws SQLException { DatabaseMetaData metaData = connection.getMetaData(); try (var tables = metaData.getTables(null, "PUBLIC", tableNamePattern, new String[]{"TABLE"})) { return ResultSetUtils.toList(tables, table -> table.getString("TABLE_NAME")); }}Put native code in another class
Section titled “Put native code in another class”Use cls and method when the native implementation should live outside the
JDBC interface.
@JdbcNative(cls = AdvancedNativeCode.class, method = "databaseProductName")String databaseName();
final class AdvancedNativeCode {
private AdvancedNativeCode() { }
public static String databaseProductName(Connection connection) throws SQLException { return connection.getMetaData().getDatabaseProductName(); }}Troubleshooting
Section titled “Troubleshooting”My batch does not write immediately
Section titled “My batch does not write immediately”That is expected.
A batch collects calls until the configured batch size is reached.
Always use try-with-resources so remaining rows are flushed on close().
I want to write a batch before it is full
Section titled “I want to write a batch before it is full”Call executeBatch() on the returned batch.
It executes the currently collected statements and resets the current batch
count.
My batch interface is rejected
Section titled “My batch interface is rejected”The return type of a @JdbcBatchUpdate method must be an interface that extends
JdbcBatch.
The batch interface must contain exactly one @JdbcUpdate method, and that
method must return void.
My native method is not found
Section titled “My native method is not found”Without cls or method, the processor searches in the same interface for a
static method with the same name.
Use @JdbcNative(cls = ..., method = "...") when the implementation is in a
different class or has a different name.
My native method signature is rejected
Section titled “My native method signature is rejected”The native implementation must be static.
Its first parameter must be Connection.
The remaining parameters must match the interface method parameters in order and
type.
The return type and checked exceptions must be compatible with the interface
method.
Exact Rules
Section titled “Exact Rules”For exact native method rules, see JDBC native. For update and batch update rules, see JDBC update. For statement and processor configuration, see processor configuration.