Roadmap¶
We ordered our milestones around one rule: tackle the biggest semantic risks first and prove real performance gains as early as possible.
Milestone Status¶
| Milestone | Scope | Status |
|---|---|---|
| M0 | Proof of concept: an ObjectWrapperFactory experiment on stock MyBatis to test the core thesis before writing any LarkBatis code |
|
| M1 | Runtime core: annotation-based processor for static SQL and #{}; $$Impl + row readers; useGeneratedKeys; SqlFragment |
|
| M2 | Gradle plugin: mapper XML; dynamic tags; expression grammar parser; differential test harness against MyBatis | |
| M3 | <foreach>, power-of-two padding (@PadPow2), batch inserts |
|
| M4 | 1-level join <resultMap>, Stream returns, transaction scopes, Spring Boot integration |
|
| M5 | Extended JMH benchmarks, legacy-mapper scanner CLI, design documentation | (except native-image smoke test) |
Completed alongside these: Maven build plugin, JPMS named module descriptors for all published artifacts, and unified Spring Boot 3 / Boot 4 compatibility.
M0: Proving the thesis cheaply¶
This milestone was about validating our core assumption with minimal effort. MyBatis has an ObjectWrapperFactory SPI, which lets you plug in a generated ObjectWrapper per result class without modifying MyBatis itself. If eliminating Reflector and MetaObject on the row-reading path made a measurable difference, our thesis was validated with just a few hundred lines of test code. If not, we could walk away before investing months of effort.
It proved the thesis decisively. See Performance.
M5: Remaining items¶
| Task | Status |
|---|---|
larkbatis-benchmarks (JMH; pinned sessions; STATEMENT-scope cache; H2 over TCP; JDK 17 vs 21; 50-bean megamorphic benchmark) |
Done. Results |
larkbatis-scanner (larkbatis-scan CLI) |
Done. Details |
| Native-image smoke test | Not yet run. Development environment lacks GraalVM setup |
| Extended 1-week production soak test of migrated service | Pending. (The initial trial migration passed 100% of its test suite) |
| Architecture documentation revision | Done |
Native image verification status
Zero runtime reflection is a structural guarantee: there are no dynamic proxies, no Class.forName, and no setAccessible calls in runtime or generated code. However, an end-to-end native-image build has not been executed yet. We treat this as an architectural design property rather than a benchmarked claim until that smoke test runs.
Deliberately deferred¶
| Feature | Reason |
|---|---|
Multiple DataSources (@LarkBatisDataSource) |
We want real production usage before locking in an API. Today: define one SpringLarkBatisSession per DataSource and wire mapper @Bean methods manually |
| Test-scoped mappers | Build plugins only configure main source sets |
log-sql |
Handled more cleanly at the JDBC pool or driver level (datasource-proxy, p6spy) |
Features that will not be added¶
These are not backlog items. Each sits on the wrong side of our shape vs value boundary, and adding them would re-introduce runtime reflection and interpretation:
Full OGNL expressions · <bind> · @SelectProvider annotations · Lazy loading · Interceptor plugins · Untyped Object/Map parameters · <discriminator> · Nested select= queries in <collection> · Second-level caches · Dynamic runtime addMapper() · RowBounds · Runtime classpath scanning · ExecutorType.
Each unsupported feature produces a clear compile-time error with its recommended alternative. See MyBatis Differences.
Versioning¶
Documentation is versioned alongside releases. Use the version selector in the header to view documentation for specific releases.