MyBatis Compatibility
MyBatis Compatibility
Section titled “MyBatis Compatibility”This document is the single compatibility classification for Lynxus. It compares Lynxus with the deterministic Mapper behavior documented by MyBatis 3.5.19; it does not promise MyBatis API, runtime, configuration, or plugin compatibility.
Classification
Section titled “Classification”Every row uses one of these statuses:
| Status | Meaning |
|---|---|
| Direct support | Lynxus has a documented contract and generated/runtime evidence for the behavior. |
| Deterministic conversion | A supported MyBatis shape can be rewritten into Lynxus declarations without runtime interpretation. |
| Skill-assisted migration | The behavior requires project inspection, ambiguity reporting, or a reviewable change produced by the migration skill in #10. |
| Explicit rejection | Lynxus rejects the behavior or deliberately does not provide its MyBatis runtime equivalent. |
The migration skill may assist with a row classified as skill-assisted migration, but it must not
invent a new compatibility rule. Compiler diagnostics and this document remain authoritative.
Evidence And Baseline
Section titled “Evidence And Baseline”MyBatis references:
- MyBatis 3.5.19 source tree
- MyBatis getting started
- MyBatis Java API
- MyBatis XML mapping
- MyBatis dynamic SQL
- MyBatis Spring
Lynxus evidence:
- Core contract
- Extension contracts
- Manual migration guide
- JDBC compatibility fixtures
- XML compiler diagnostics
- Generated-source tests
- External Maven consumer fixture
- External Gradle consumer fixture
The JDBC value-type comparison is owned by the Core contract and its PostgreSQL/MySQL tests. This document classifies product behavior and links to that evidence; it does not duplicate the handler-by-handler JDBC table.
Compatibility Matrix
Section titled “Compatibility Matrix”Mapper API And SQL Sources
Section titled “Mapper API And SQL Sources”| MyBatis capability | Status | Lynxus boundary and migration action | Evidence |
|---|---|---|---|
| Mapper interfaces and CRUD methods | Deterministic conversion | Replace MyBatis annotation imports with io.github.lynxus.annotation declarations. Generated implementations are ordinary classes constructed with SqlExecutor. |
Core contract, migration guide |
@Select, @Insert, @Update, @Delete |
Direct support | Use the Lynxus equivalents. Static SQL and the controlled script subset compile into Java. | Core contract |
@Param and common parameter aliases |
Direct support | Prefer explicit names for multi-parameter methods. Names and property paths are resolved at compile time. | Core contract |
@Options and arbitrary statement options |
Explicit rejection | Lynxus currently emits default options from generated Mappers. Custom plan construction may set the documented JDBC options; no Mapper @Options contract exists. |
Core contract |
| SQL providers | Deterministic conversion | Rewrite provider declarations to @UseSqlProvider for runtime SQL structure, with compile-time validation of provider shape and typed BoundSql. |
Extension contracts, migration guide |
| Custom parameter and result handlers | Deterministic conversion | Replace a parameter handler with ParameterBinder and a row/result handler with RowMapper; there is no global runtime handler registry. |
Extension contracts, Core contract |
XML And Dynamic SQL
Section titled “XML And Dynamic SQL”| MyBatis capability | Status | Lynxus boundary and migration action | Evidence |
|---|---|---|---|
| Static Mapper XML statements | Direct support | Keep XML at the Mapper resource path. Supported declarations compile at annotation-processing time. | Core contract |
select, insert, update, delete, and batch declarations |
Direct support | Use the controlled top-level subset. IDs must be non-blank and unique within the resource. | Core contract, XML diagnostics |
if, choose, when, otherwise, trim, where, set, foreach, bind |
Deterministic conversion | Use the supported expression subset. Java control flow and SQL assembly are generated; no OGNL engine runs at runtime. | Core contract, migration guide |
sql and include fragments |
Direct support | Fragment IDs and references are validated across the complete resource. Missing and cyclic references fail compilation. | Core contract, XML diagnostics |
| XML namespaces and declaration integrity | Deterministic conversion | <mapper namespace> must equal the fully qualified Mapper name. Unsupported top-level tags, attributes, malformed declarations, and invalid unused declarations fail compilation. |
Core contract, XML diagnostics |
${} substitution |
Explicit rejection | Use bound #{} values or a provider for validated SQL structure. Lynxus never treats unsafe substitution as plain text. |
Core contract, migration guide |
| Arbitrary OGNL, static calls, and unsupported method calls | Explicit rejection | Rewrite into the supported expression subset or move SQL structure to a typed provider. | Core contract |
| Runtime XML reload or interpretation | Explicit rejection | Recompile after changing XML. XML is not loaded by the runtime executor. | Design philosophy |
Result Mapping And Execution
Section titled “Result Mapping And Execution”| MyBatis capability | Status | Lynxus boundary and migration action | Evidence |
|---|---|---|---|
| Scalar, record, JavaBean, list, and optional results | Direct support | Use generated flat result mapping. Query cardinality is explicit through typed results and generated return adaptation. | Core contract, Core contract |
Flat resultMap declarations |
Deterministic conversion | Use scalar mappings, JavaBean <id> / <result>, or record <constructor> arguments. All declarations and references are validated at compile time. |
Core contract, XML diagnostics |
Nested association, collection, and graph aggregation |
Explicit rejection | Flatten the query, use explicit follow-up queries, use a one-row RowMapper, or use raw JDBC. |
Core contract, migration guide |
| Lazy loading and nested selects | Explicit rejection | Make loading explicit in application/service code. | Design philosophy |
| Generated keys | Direct support with constraints | Use one static insert with an explicit non-blank key column and one supported returned key value. Batch, dynamic, and provider generated keys are outside the contract. | Core contract |
| JDBC batch execution | Direct support | Use Lynxus @Batch or XML <batch> with one List<T> argument and the driver-provided counts. |
Core contract |
| Cursor/streaming results | Deterministic conversion | Adapt cursor consumers to RowCursor callbacks. Cursors and streams cannot escape executor cleanup. |
Core contract, Extension contracts |
| MyBatis built-in JDBC value handlers | Deterministic conversion | Use Lynxus’s fixed Core routes. The supported Java/JDBC matrix and database evidence live in the Core contract. | Core contract, Core contract |
| Unsupported or lifecycle-bound JDBC values | Explicit extension | Materialize through a RowMapper/ParameterBinder or use raw JDBC. JDBC resources do not escape cleanup. |
Core contract, Extension contracts |
Sessions, Transactions, Spring, Plugins, And Caches
Section titled “Sessions, Transactions, Spring, Plugins, And Caches”| MyBatis capability | Status | Lynxus boundary and migration action | Evidence |
|---|---|---|---|
SqlSession and session-scoped runtime state |
Explicit rejection | Inject or construct generated Mapper implementations with one SqlExecutor; transaction ownership is explicit. |
Design philosophy, Core contract |
| Local transactions | Direct support | Use one JdbcAssembly and its callback transaction executor. Nested failures preserve rollback-only semantics. |
Core contract |
| Spring transaction participation | Deterministic conversion | Use the Spring starter for DataSource binding and transaction participation. Spring owns transaction policy; Core still owns JDBC execution. | Extension contracts, Spring guide |
| Advanced propagation, savepoints, distributed transactions, and recovery | Explicit rejection | Delegate host transaction policy to Spring or another transaction system. Lynxus does not coordinate distributed commits. | Core contract |
| First/second-level or session cache | Explicit rejection | Use an application cache outside Lynxus. The opt-in QueryCache adapter is a successful-SELECT cache, not a MyBatis session identity map. |
Design philosophy, Extension contracts |
| MyBatis plugin/interceptor chain | Explicit rejection | Use ExecutionInterceptor for observation or a typed whole-execution adapter for the documented plan replacement/short-circuit cases. These adapters cannot intercept JDBC phases, mutate generated binding/mapping, or provide full MyBatis plugin compatibility. |
Extension contracts, Core contract |
| Runtime Mapper proxies | Explicit rejection | Use generated implementation classes directly or register them through the Spring starter. | Core contract |
Migration Decision Rules
Section titled “Migration Decision Rules”- Keep a method in annotations or XML when its SQL, parameters, dynamic branches, and flat result shape fit a
direct supportordeterministic conversionrow. - Use a typed provider, binder, row mapper, interceptor, or Spring adapter only when the corresponding Lynxus contract owns the behavior.
- Send ambiguous or project-wide transformations to the migration skill. It must produce a reviewable diff and intervention report rather than guess.
- Stop and report the construct for
explicit rejection; do not add runtime reflection, OGNL, a global registry, a session abstraction, or a SQL-rewrite plugin to bypass the boundary.
The manual workflow is documented in Migrating From MyBatis. The automated, reviewable workflow is owned by issue #10 and must consume this matrix rather than copy it.