Releases: storm-orm/storm-framework
Release list
1.12.0
Storm 1.12.0
Storm 1.12 is a feature release focused on the Kotlin developer experience — a fully reified query API — alongside a batch of correctness fixes for joins, foreign-key resolution, and dialect-specific SQL, plus safer-by-default schema validation.
Requires Kotlin 2.0+ and Java 21+.
Operational changes
- Query/join builders are now abstract classes.
QueryBuilder,JoinBuilder, andTypedJoinBuilderchanged from interfaces to abstract classes so they can host Kotlinreifiedmembers. Source-compatible if you only chain on the builders, but binary-incompatible — recompile any precompiled code against 1.12. (#167) - Schema validation is enabled by default. The Spring Boot starters and the Ktor plugin now run schema validation in
failmode by default: an application whose entity model and database schema disagree refuses to start. Setstorm.validation.schema_mode(Spring) /storm.validation.schemaMode(Ktor) towarnornoneto relax or opt out. (#170)
New features
Reified Kotlin query API (#167, #161)
The ::class-based Kotlin API now has fully reified alternatives:
- Joins — chained:
innerJoin<Rating>().on<Movie>()(plusleftJoin/rightJoin/crossJoin/typed, and customon { "..." }); or the combined block DSL:innerJoin<Owner, Pet>(). - Selects —
select<R, _, _> { template }onEntityRepository/ProjectionRepository, andselectFrom<T, R> { template }onQueryTemplate. - Repository lookup —
orm.entity<User>()/orm.entity<User, _>()andprojection<T>()/projection<T, _>(). - Query results — reified terminals on
Query:resultList<T>(),singleResult<T>(),optionalResult<T>(),resultStream<T>(),resultFlow<T>(), so the advertisedorm.query { ... }.resultList<User>()now compiles.
findBy repository shortcuts for Java 21 (#161)
findBy / getBy / findAllBy / findRefBy / findAllRefBy / getRefBy convenience methods on EntityRepository and ProjectionRepository, mirroring the Kotlin API. Template-based groupBy / having / orderBy on QueryBuilder are now public (were protected).
storm-ktor-koin — new module (#171)
A new optional module for Ktor apps that use Koin for dependency injection. Application.stormModule() returns a Koin Module exposing the ORMTemplate and every auto-registered repository, each bound under its own interface type, so services declare repositories as plain constructor parameters:
install(Koin) {
modules(stormModule(), module { singleOf(::OrderService) })
}Registered in the parent aggregator and the BOM.
Automatic repository registration in Ktor (#167)
Repositories from the compile-time type index now register automatically when the Storm plugin is installed — stormRepositories { } is optional. Application and ApplicationCall gain reified entity / projection / repository accessors.
Migration hook for Ktor (#170)
A new migration { dataSource -> ... } plugin hook runs after the DataSource is available (including the zero-config HOCON pool) and before the template is created and the schema validated, so Flyway or Liquibase run in the right order.
Improvements & fixes
- Key chains for foreign keys (#166). A foreign key to an entity whose primary key is itself an entity reference now resolves to the referenced key's actual columns instead of a single
<field>_id, fixing every operation on dependent one-to-one chains. Foreign-key columns are now schema-validated through the chain, and a newColumn.persistedType()gives dialects the persisted Java type without needing to know key structure. - Dependency-aware join ordering (#169). Fixed generated SQL that produced forward alias references when outer joins are present — rejected by PostgreSQL (
missing FROM-clause entry) though silently tolerated by H2. Joins are now ordered so an alias is always declared before use, outer joins move as late as dependencies allow, and the select-table outer→INNER conversion runs before ordering. - JSpecify
@NonNullnullability (#169).org.jspecify.annotations.NonNullis now recognized when deriving record-component nullability (alongside jakarta/javax@Nonnull). A bare@FKwithout a non-null marker still degrades toLEFT JOIN. - Typed joins onto projections (#163).
.on(Projection.class)/.on<Projection>()now resolves by table match rather than requiring a template ON clause. Ambiguous foreign-key joins (a type with multiple FKs to the same table) now fail fast at query time with a descriptive error naming the candidate fields, instead of silently joining through the first one. @Json→ PostgreSQLjsonb(#165). JSON converter output is now bound so PostgreSQL acceptsjson/jsonbcolumns (previouslysetString, which PostgreSQL rejects), matching the documented JSONB recommendation. Verified against realjsonbcolumns (insert / update /ON CONFLICTupsert / batch).- H2 natural-key upserts (#165). MERGE-source parameters are cast to the H2 types matching how the ORM binds each value, re-enabling six previously-disabled upsert tests. H2/Oracle/SQL Server MERGE code is consolidated into one shared base.
@StormTestscript splitting (#165). SQL scripts are split with a comment- and literal-aware scanner, so a;inside a comment, string literal, or quoted identifier no longer breaks every test using the script.- FK-first join order (#162). All join emitters render the referencing (FK) column on the left and the referenced key on the right, consistently across join directions and JOINED inheritance (cosmetic; join semantics unchanged).
- Spring Boot 4 compatibility (#162).
StormTransactionAutoConfigurationreferencesDataSourceTransactionManagerAutoConfigurationby name across both the 3.x and 4.x (modularspring-boot-jdbc) class locations.
Documentation
Docs and examples were updated throughout to the reified Kotlin syntax, plus a 5-minute quickstart, a framework comparison page, an end-to-end "Build a REST API" tutorial, and a set of task and migration tutorials. The three example projects (Kotlin + Ktor, Kotlin + Spring Boot, Java + Spring Boot) were simplified to the new defaults (repository auto-registration, on-by-default schema validation, and Koin wiring for the Ktor example).
Upgrading
- Recompile against 1.12 — the builder interface→abstract-class change is binary-incompatible.
- Schema validation now fails startup on a model/schema mismatch. Ensure your migrations run before validation (Spring: any bean-based mechanism completes first; Ktor: use the new
migration { }hook), or setstorm.validation.schema_mode/schemaModetowarnornone.
Full changelog: v1.11.6...v1.12.0
1.11.6
Features
- Kotlin 2.4 support — added the storm-compiler-plugin-2.4 variant (built against the Kotlin 2.4.0 compiler API) so projects on Kotlin 2.4.x can use the SQL-template auto-interpolation plugin. (#149)
Fixes
- @convert on an embedded (@inline) component field failed on save. The converter invoked the field accessor on the root record instead of the embedded component that declares it, throwing ClassCastException (“object is not an instance of declaring class”). Storm now resolves the declaring record before applying the converter. Affected all converters (default and Jackson). (#141)
- CLI: regex injection via MCP alias. The storm CLI interpolated a user-supplied --alias directly into a regular expression when editing .codex/config.toml; a crafted alias could match/remove the wrong section. The server name is now regex-escaped at both call sites (fixes CodeQL js/regex-injection). (#145)
1.11.5
Documentation and tooling release.
Fixes
- Correct the quick-start install command to
npx @storm-orm/cli; the
previously documented@storm/clipackage does not exist on npm. - Repoint documentation badges and links to the canonical site, https://orm.st
(the old GitHub Pages URL returned 404).
Documentation
- Redraw the Schema-First / Entity-First AI workflow diagram so both flows
converge on validation, with each step labeled by actor: You / AI generate,
Flyway / H2 apply, Storm verifies (#139).
Project & tooling
- Add a security policy, code of conduct, and issue / PR templates (#138).
- Fix
@storm-orm/clipackage metadata (repository URL, bin path) and
improve the release workflow.
1.11.4
Improvements
- Improve handling of NULL for optional results in Query and QueryBuilder (Java and Kotlin), so optional single-result lookups behave consistently when a column or row is null (#131)
- Optimize object mapping for value types, reducing per-row mapping overhead in the query execution path (#129)
Fixes
1.11.3
Additions
- Add validateSchema(Predicate<Class<? extends Data>>) and validateSchemaOrThrow(Predicate<Class<? extends Data>>) overloads on ORMTemplate (Java and Kotlin), letting multi-datasource applications validate
only the subset of discovered types reachable from each connection - Add validateAndReport(Predicate, strict) and validateReportAndThrow(Predicate, strict) on SchemaValidator to support the new filter-based validation API
- Add storm mcp update command to re-register all configured MCP connections after editor config drift, replacing the previous bare-storm mcp re-registration behavior
- Add storm mcp as the standalone MCP setup entry point (with storm mcp init retained as an alias), so the primary onboarding command is now npx @storm-orm/cli mcp
Improvements
- Always return JDBC connections to the pool on transaction completion, even when commit() or rollback() throws — previously a failed commit could leave a connection with autoCommit=false in the pool, breaking
the auto-commit precondition on the next transaction - Improve upsert failure error messages with singular/plural phrasing based on batch size and an explicit hint to verify the @pk generation strategy when the primary key is not auto-generated
- Add upsertFailureMessage(int batchSize) as a protected extension point on EntityRepositoryImpl so dialect-specific subclasses (H2, MySQL, PostgreSQL, MSSQL, Oracle, SQLite) share a consistent message
- Add USE to the default SQL reserved-keyword set so identifiers colliding with the MySQL/MariaDB USE statement are quoted correctly
- Coerce stringified JSON arrays in MCP select_data arguments (columns, where, orderBy, and IN operator values) so clients that pass arrays as strings still work
- Track newly created skills separately from updated/appended skills in storm update, giving clearer install output when re-running against existing agent configs
- Update agent-rule installation to insert or replace the ## Database Schema Access block in-place between Storm markers, instead of duplicating it
Documentation
- Add DI preference guidance to the Java and Kotlin Storm skills: in Spring Boot and Ktor projects, repositories must be constructor-injected; orm.entity() / orm.repository() lookups are reserved for
standalone code and tests - Add the "queries belong in repository interfaces" rule to the Kotlin query/repository skills, with explicit examples for Spring Boot, Ktor, and standalone setups
- Add code-first WHERE clause guidance to the Kotlin query skill: use metamodel predicates (eq, isTrue(), isNotNull(), FK paths) and fall back to template strings only for expressions predicates cannot express
- Add a complete select_data parameter reference to the schema-rules skill (table, columns, where, orderBy, offset, limit) with operator list and example payload
- Clarify select_data result-presentation guidance: show the markdown table directly, never transpose or narrate the data in prose
- Update database-and-mcp.md for the new storm mcp / storm mcp update command structure
1.11.2
Additions
- Add storm db command group for managing a global database connection library (storm db add, storm db list, storm db remove, storm db config), separating credentials from project configuration
- Add multi-database MCP support with storm mcp add/list/remove, allowing a single project to connect multiple databases (even across different dialects) with named aliases
- Add optional read-only data access via select_data MCP tool, letting AI query individual records to inform type decisions (e.g., recognizing enum-like values or JSON columns), with read-only enforced at the database
driver level - Add table exclusion configuration (storm db config) to restrict select_data access on a per-table basis
- Add reverse unique key validation in SchemaValidator: single-column database unique constraints now warn if the corresponding entity field is missing @uk, while composite constraints are left unmodeled by default
- Add compile-time validation in metamodel processors (Java and Kotlin) that @pk, @fk, and @uk are not placed on inline record fields
- Add entityId() and projectionId() Kotlin extension functions on Ref for type-safe ID extraction without unsafe casts
- Add unique constraints and FK cascade rules (onDelete/onUpdate) to describe_table MCP output across all supported dialects
- Add type-ahead filtering and viewport scrolling to the CLI checkbox prompt for large selection lists
Improvements
- Enforce read-only database connections in MCP server (PostgreSQL: default_transaction_read_only=on, MySQL/MariaDB: SET SESSION TRANSACTION READ ONLY, SQL Server: readOnlyIntent)
- Clarify @uk documentation: compound unique constraints only need modeling when a composite Metamodel.Key is required; @uk(constraint = false) suppresses validation when no database constraint exists
- Streamline AI setup documentation, extracting tool configuration matrix and skills table into a dedicated AI Tools Reference page
Documentation
- Add database-and-mcp.md with full guide for global connections, project aliases, data access, security model, and multi-database setup
- Add ai-reference.md listing configuration locations, skills, and database skills per AI tool
- Update entities.md with reorganized compound unique key section and guidance on when modeling is (and isn't) needed
- Update AI skills for unique constraint nuance, typed Ref ID extraction (entityId/projectionId), select_data usage, Ref in aggregation result types, and varargs metamodel groupBy
1.11.1
Additions
- Add Slice as common base interface for Window (cursor-based scrolling) and Page (offset-based pagination), defining content(), hasNext(), and hasPrevious()
- Add findAllRef() on EntityRepository and ProjectionRepository for retrieving all refs without loading full entities
- Add select(predicate) and selectRef(predicate) convenience methods on EntityRepository and ProjectionRepository as shorthand for select().where(predicate)
- Add removeAll(predicate) convenience method on EntityRepository for deleting matching entities and returning count
- Add typed Window.next() and Window.previous() navigation methods with type inference from call-site context
- Add automatic Ref and Data parameter resolution in SQL templates, allowing Ref and entity instances as bind variables without manually extracting the ID
- Add Codex IDE support in Storm CLI
Improvements
- Simplify repository API by removing Stream/Flow-based selectById and selectByRef overloads
- Enforce explicit predicate consumption in DSL blocks (applyResult → validateResult); unconsumed return values now throw IllegalStateException
- Simplify QueryModel element resolution by removing context-dependent validation and operator patterns
Documentation
- Update all documentation for delete → remove rename
- Update pagination-and-scrolling.md with Slice hierarchy and Window type parameter
- Update repositories.md with removeAll/removeBy patterns and select(predicate) shorthand
- Comprehensive AI skills and LLM reference documentation updates
1.11.0
Additions
- Add cursor-based scroll API with Scrollable, Window, and MappedWindow
- Add opaque cursor serialization with CursorCodec and CursorFactory SPI for type-safe cursor encoding/decoding
- Add SQLite dialect module (storm-sqlite) with full entity repository and schema validation support
- Add H2 dialect module (storm-h2) with full entity repository and schema validation support
- Add Ktor integration modules (storm-ktor, storm-ktor-test) for using Storm outside Spring Boot
- Add transaction callbacks (onCommit, onRollback) on the Transaction interface, with support for suspend lambdas and proper propagation across nested transactions
- Add block-based SQL DSL for Kotlin with select {} and delete {} builders, @DslMarker scope control, and automatic predicate application
- Add Storm CLI (storm-cli) for AI-assisted development setup across Claude Code, Cursor, and GitHub Copilot
- Add SqlDialectProvider SPI for pluggable dialect auto-discovery based on database product name
- Add custom DataSource factory support in @stormtest via static dataSource() method, enabling Testcontainers integration
- Add Timestamp parameter binding hook to SqlDialect for round-trip consistency in optimistic lock comparisons
- Add JpaTemplate.ORM overloads that accept a custom TemplateDecorator
Improvements
- Simplify repository API
- Track connection ownership by transaction context instead of thread identity, fixing concurrent access detection for coroutines resuming on different virtual threads
- Improve script path resolution in @stormtest with support for classpath: prefix and relative paths
- Add StormConfigHelper for safe configuration parsing with fallback defaults and warning logs
- Improve schema validation
- Improve AI content with comprehensive skills, rules, and MCP server support
Documentation
- Add pagination-and-scrolling.md documentation for the new scroll API
- Add cursors.md documentation for opaque cursor serialization
- Add ktor-integration.md documentation for the Ktor plugin
- Add transactions.md documentation for transaction callbacks and propagation
- Add ai.md guide for AI-assisted development setup
- Comprehensive documentation updates across all major topics
1.10.0
Additions
- Add Kotlin Compiler Plugin (storm-compiler-plugin) for SQL Template DSL, replacing the storm-kotlin-validator lint rules with compile-time t() wrapping
- Add multi-dollar string support in SQL templates
- Add built-in offset-based pagination support with Page and Pageable
- Add constraint validation flag to PK, FK, and UK annotations for suppressing individual schema validation checks
- Add unsaved entity detection for foreign keys during insert/update
- Add streamingRequiresTransaction to correctly apply fetch size for streaming result sets
Improvements
- Use fetchSize to limit memory consumption for large (streaming) result sets
- Optimize memory footprint
- Improve error reporting with actionable suggestions in schema validation messages
- Clean up API naming: rename StatementCapture to SqlCapture and CapturedStatement to CapturedSql
- Improve schema validation timing in Spring Boot auto-configuration
- Improve CI pipeline
Documentation
- Add string-templates.md documentation for the new compiler plugin
- Comprehensive documentation updates across all major topics