Troubleshooting¶
Nothing is generated during build¶
Check the following in order:
- Is the processor on the correct configuration? Use
annotationProcessorin Gradle, or<annotationProcessorPaths>in Maven (notimplementationor standard<dependencies>). - Are you compiling with standard javac? ECJ / Eclipse batch compiler is not supported because the processor relies on javac's AST element ordering and multi-round type resolution.
- Does the interface have statement annotations or
@Mapper? Purely XML-based mappers must have@Mapperon the interface so javac knows to pass them to the processor. - Running JDK 23+ with
addProcessorPath=false? javac on JDK 23+ no longer discovers processors from the compilation classpath automatically. Add the processor to<annotationProcessorPaths>or pass<proc>full</proc>.
#{id} does not resolve, or parameters are named arg0, arg1¶
In Gradle, incremental compilation can invoke annotation processors over existing class files where parameter names were stripped (unless compiled with -parameters). Clean builds succeed because they parse Java source files directly, but subsequent incremental builds fail.
The -parameters compiler flag¶
Lombok conflicts / "Result class has no accessors"¶
Lombok generates getters and setters in the AST during compilation. Because javac runs processors in the order they appear on the classpath, placing LarkBatis before Lombok means LarkBatis sees classes without getters/setters.
Always declare Lombok first:
annotationProcessor("org.projectlombok:lombok")
annotationProcessor("io.github.larkbatis:larkbatis-processor:0.1.0") // must be after Lombok
Editing mapper XML does not trigger recompilation¶
Annotation processors cannot easily track resource file edits automatically, which is why build plugins are used:
- Using a build plugin? Gradle registers XML files as compilation inputs; Maven's
larkbatis:refreshgoal touches mapper interfaces when XML changes. - Maven plugin not running? Ensure you added
<extensions>true</extensions>tolarkbatis-maven-plugin. Without this, Maven silently ignores build extensions. Runmvn larkbatis:checkto verify. - Passing
-Alarkbatis.mapperDirmanually? Run./gradlew cleanormvn cleanafter editing XML files.
Also verify that XML root tags are <mapper> and that the namespace matches an interface in the same compilation module.
package javax.annotation.processing is not visible¶
In modular JPMS projects, add requires static java.compiler; to your module-info.java because generated code includes @Generated annotations. See Java Modules.
useGeneratedKeys without keyColumn falls back to RETURN_GENERATED_KEYS¶
Always specify keyColumn when using useGeneratedKeys = true. RETURN_GENERATED_KEYS returns ROWID on Oracle and all columns on PostgreSQL. Specifying keyColumn = "id" guarantees consistent cross-database behavior. See Generated Keys.
LarkBatisEmptyForeachException at runtime¶
An empty collection was passed to a <foreach> block. In MyBatis, an empty collection generates malformed SQL that crashes at the database. In LarkBatis, it throws an informative exception immediately.
To skip the SQL fragment when a list is empty, wrap it in an <if> tag:
<if test="ids != null and !ids.isEmpty()">
AND id IN <foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
</if>
test="count" causes a compile error¶
LarkBatis intentionally rejects OGNL truthiness. Write explicit comparisons: count != 0, user != null, or !list.isEmpty(). See Dynamic SQL.
String parameter bound to ${} causes a compile error¶
Direct string splicing into ${} is prohibited to prevent SQL injection vulnerabilities. Use @OrderBy(allowed = {...}), SqlFragment, or closed-value types (enums/integers). See Raw SQL.
LarkBatisRollbackOnlyException on commit¶
An inner transaction scope exited with an error or without voting to commit, poisoning the transaction. When the outer transaction scope attempted to commit, it threw LarkBatisRollbackOnlyException to avoid silent data loss. See Transactions.
LarkBatisUnboundedVariantsException¶
If fail-on-unbounded-fragment: true is enabled and a statement exceeds max-sql-variants, it throws this exception. Use SqlFragment.allowed(...), @OrderBy, or @PadPow2 to bound dynamic SQL variants. See Raw SQL.
Statement fell back to name-based row reads¶
If javac cannot parse a statement's SELECT column list (e.g. SELECT * or ${} inside the column list), it falls back to reading columns by name via ResultSetMetaData on the first row. While fully functional, it is slightly slower than indexed reads. Provide explicit column names and aliases to restore fast indexed reading.