Annotations¶
Here is the complete reference for annotations in io.github.larkbatis.annotations. All annotations use CLASS retention: they are read by the compiler during build time and discarded from bytecode at runtime. Modular projects can declare them via requires static io.github.larkbatis.annotations;.
Statement Annotations¶
@Select, @Insert, @Update, @Delete¶
Accepts String[] (lines are joined with a single space). Applied directly to mapper methods:
@Select({
"SELECT id, name, email, created_at",
"FROM users",
"WHERE email = #{email}"
})
User findByEmail(String email);
Each method must define its SQL using either an annotation or XML. Having both or neither is a compile error.
@Mapper¶
Marks an interface whose statements are defined in mapper XML. The XML file's namespace must match the interface's fully-qualified class name, and statement ids must match method names.
Purely annotation-based mappers do not need @Mapper: javac discovers them automatically from their @Select/@Insert annotations.
@Param¶
Names a method parameter for #{} binding. Required when a method has multiple parameters unless compiled with the javac -parameters flag.
@Select("SELECT id, name FROM users WHERE name LIKE #{pattern} AND id > #{after}")
List<User> page(@Param("pattern") String pattern, @Param("after") long after);
@Options¶
@Retention(CLASS) @Target(METHOD)
public @interface Options {
boolean useGeneratedKeys() default false;
String keyProperty() default "";
String keyColumn() default "";
}
Configures primary key retrieval after an INSERT statement:
| Attribute | Description |
|---|---|
useGeneratedKeys |
Set to true to retrieve database-generated keys |
keyProperty |
Target property on parameter object (e.g. "id" or "user.id"). Required when useGeneratedKeys is true |
keyColumn |
Database column name(s). Strongly recommended for consistent driver behavior. See Generated Keys |
For composite keys, provide matching comma-separated lists:
@Insert("INSERT INTO users (name, email) VALUES (#{name}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
int insert(User u);
@OrderBy¶
Allows a String parameter to be safely spliced into dynamic ${} SQL clauses by validating it against a static whitelist at runtime via a generated switch statement. Inputs outside the allowed list throw LarkBatisRejectedException.
@Select("SELECT id, name, email, created_at FROM users ORDER BY ${sort}")
List<User> all(@OrderBy(allowed = {"id", "name", "created_at"}) String sort);
Without @OrderBy, binding a plain String to ${} fails compilation. See Raw SQL.
@PadPow2¶
Rounds <foreach> placeholder counts in IN clauses up to the next power of two by repeating the last element, bounding dynamic SQL statement variants to $\log_2(N)$ instead of $N$.
Can be applied at the interface level or on individual methods:
Restricted to IN clauses
Repeating parameters is only valid when duplicate elements don't affect query semantics. The compiler enforces that @PadPow2 is only used on SELECT/UPDATE/DELETE statements with simple single-item #{} binds, and rejects its use on INSERT queries.
@Column¶
Overrides the default snake_case → camelCase column mapping for a specific field or accessor:
public class Contact {
@Column("contact_id")
private long id;
private String email;
private String phone;
@Column("usr_email")
public void setEmail(String email) { this.email = email; }
@Column("mobile")
public String getPhone() { return phone; }
}
Can be placed on fields, getters, or setters. (Placing conflicting @Column names on the same property is a compile error).
@LarkBatisRow¶
Generates a static RowReader for classes used exclusively in custom escape-hatch queries rather than standard mapper return types:
@LarkBatisRow
public class DomainCount {
private String domain;
private long total;
// standard getters and setters
}
default List<DomainCount> countByDomain(LarkBatisSession s, int minimum) {
return s.query(
SqlFragment.unsafeRawSql("SELECT ... GROUP BY domain HAVING COUNT(*) >= ?"),
ps -> ps.setInt(1, minimum),
DomainCountRow.READER); // generated via @LarkBatisRow
}
@Handler¶
@Retention(CLASS) @Target({PARAMETER, FIELD, METHOD})
public @interface Handler { Class<?> value(); }
Specifies a custom LarkBatisTypeHandler for a specific parameter, field, getter, or setter. Generated code calls the handler directly without runtime registry lookups.
public class Wallet {
@Handler(MoneyHandler.class)
private Money balance;
}
@Select("SELECT id FROM wallet WHERE balance >= #{floor}")
List<Long> atLeast(@Handler(MoneyHandler.class) Money floor);
See Custom Type Handlers for implementation details.