Runtime API¶
Here is the public API in io.github.larkbatis.runtime. The runtime has zero dependencies beyond standard JDBC—no reflection, no dynamic proxies, and no runtime type inspection.
LarkBatisSession¶
The runtime session contract used by all generated mappers:
public interface LarkBatisSession {
Connection conn(); // (1)!
void release(Connection c); // (2)!
RuntimeException translate(SQLException e, String sql);
// Escape hatch for dynamic SQL
default <T> List<T> query(SqlFragment, StatementBinder, RowReader<T>);
default <T> T queryOne(SqlFragment, StatementBinder, RowReader<T>);
default <T> Stream<T> queryStream(SqlFragment, StatementBinder, RowReader<T>);
default int update(SqlFragment, StatementBinder);
// Internal helpers for Stream returns
default <T> Stream<T> stream(Connection, PreparedStatement, ResultSet, RowReader<T>, String);
default RuntimeException streamFailed(Connection, PreparedStatement, ResultSet, String, SQLException);
}
conn(): Returns the connection bound to the active transaction, or opens a new auto-commit connection if running standalone.release(Connection c): Returns the connection. A no-op if part of an active transaction; closes the connection otherwise.
Implementations: JdbcLarkBatisSession (standalone Java) and SpringLarkBatisSession (larkbatis-spring).
JdbcLarkBatisSession¶
Standalone implementation of LarkBatisSession:
public JdbcLarkBatisSession(DataSource dataSource)
public LarkBatisTx begin()
public LarkBatisTx begin(boolean readOnly)
public boolean hasActiveTransaction()
LarkBatisTx¶
Transaction scope for standalone applications using try-with-resources:
| Method | Description |
|---|---|
commit() |
Votes to commit. The physical commit executes when the outermost scope closes |
rollbackOnly() |
Explicitly marks the transaction as rollback-only |
close() |
Exiting the block without voting to commit triggers an automatic rollback |
Scopes support nesting: inner scopes join the existing outer transaction. See Transactions.
SqlFragment¶
The safe wrapper for dynamic SQL text:
public static SqlFragment allowed(String value, String... allowed) // (1)!
public static SqlFragment identifier(String value) // (2)!
public static SqlFragment unsafeRawSql(String value) // (3)!
public String text()
allowed(...): Validates against a static whitelist. (Recommended).identifier(...): Validates SQL identifiers (alphanumeric and underscores).unsafeRawSql(...): Slices raw SQL text. Searchable across codebases viagrep -rn unsafeRawSql src/.
LarkBatisSql¶
Static utility helpers called by generated bytecode:
| Helper | Description |
|---|---|
trackVariants(statementId, sql) |
Monitors distinct SQL text variants per statement |
maxSqlVariants(int limit) |
Sets threshold for dynamic SQL text variants (default 64) |
failOnUnboundedVariants(boolean) |
Throws exception instead of logging warning when threshold exceeded |
padPow2(int n) |
Calculates power-of-two padding length for @PadPow2 |
sum(int[] updateCounts) |
Aggregates result counts for JDBC batch execution |
JdbcCodec¶
Static helpers for null-safe primitive conversions and enum/date mappings:
- Reads:
booleanOrNull,byteOrNull,shortOrNull,intOrNull,longOrNull,floatOrNull,doubleOrNull,instant,localDateTime,localDate,localTime,enumValue - Writes:
setBoolean,setByte,setShort,setInt,setLong,setFloat,setDouble,setInstant,setLocalDateTime,setLocalDate,setLocalTime,setEnum
public static Long longOrNull(ResultSet rs, int column) throws SQLException {
long v = rs.getLong(column);
return rs.wasNull() ? null : v;
}
Standard types with built-in null handling (String, BigDecimal, byte[], Timestamp) use direct JDBC methods.
RowReader<T> and StatementBinder¶
@FunctionalInterface
public interface RowReader<T> {
T read(ResultSet rs) throws SQLException;
}
@FunctionalInterface
public interface StatementBinder {
void bind(PreparedStatement ps) throws SQLException;
}
Every generated row reader class exposes a public static final RowReader<T> READER instance. Custom escape-hatch queries reuse these static readers with zero runtime reflection.
Exceptions¶
All exceptions are unchecked and extend LarkBatisException:
| Exception | Description |
|---|---|
LarkBatisException |
Base runtime exception wrapping underlying SQLExceptions |
LarkBatisRejectedException |
Thrown when an input to SqlFragment or @OrderBy is rejected by the whitelist |
LarkBatisEmptyForeachException |
Thrown when an un-guarded <foreach> collection is empty |
LarkBatisNoKeyException |
Thrown when useGeneratedKeys = true is set but the driver returned no keys |
LarkBatisKeyCountMismatchException |
Thrown when a batch insert receives fewer generated keys than inserted rows |
LarkBatisUnboundedVariantsException |
Thrown when dynamic SQL variants exceed max-sql-variants with fail-fast enabled |
LarkBatisRollbackOnlyException |
Thrown when attempting to commit a transaction poisoned by an inner scope error |
In Spring environments, translate() automatically converts errors to Spring's DataAccessException hierarchy (e.g. DuplicateKeyException). See Errors.