Skip to content

Commit 2a3ea50

Browse files
authored
Add Sqlite and H2 dialects. (#96) (#106)
Add Sqlite and H2 dialects. (#96)
1 parent fc19218 commit 2a3ea50

75 files changed

Lines changed: 7851 additions & 213 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,13 @@ Guides for evaluating Storm and transitioning from other frameworks.
246246

247247
Storm works with any JDBC-compatible database. Dialect packages provide optimized support for:
248248

249+
[![Oracle](https://img.shields.io/badge/Oracle-F80000?style=for-the-badge&logo=oracle&logoColor=white)](https://www.oracle.com/database/)
250+
[![SQL Server](https://img.shields.io/badge/SQL%20Server-CC2927?style=for-the-badge&logo=microsoftsqlserver&logoColor=white)](https://www.microsoft.com/sql-server)
249251
[![PostgreSQL](https://img.shields.io/badge/PostgreSQL-336791?style=for-the-badge&logo=postgresql&logoColor=white)](https://www.postgresql.org/)
250252
[![MySQL](https://img.shields.io/badge/MySQL-4479A1?style=for-the-badge&logo=mysql&logoColor=white)](https://www.mysql.com/)
251253
[![MariaDB](https://img.shields.io/badge/MariaDB-003545?style=for-the-badge&logo=mariadb&logoColor=white)](https://mariadb.org/)
252-
[![Oracle](https://img.shields.io/badge/Oracle-F80000?style=for-the-badge&logo=oracle&logoColor=white)](https://www.oracle.com/database/)
253-
[![SQL Server](https://img.shields.io/badge/SQL%20Server-CC2927?style=for-the-badge&logo=microsoftsqlserver&logoColor=white)](https://www.microsoft.com/sql-server)
254+
[![SQLite](https://img.shields.io/badge/SQLite-003B57?style=for-the-badge&logo=sqlite&logoColor=white)](https://www.sqlite.org/)
255+
[![H2](https://img.shields.io/badge/H2-0000bb?style=for-the-badge&logoColor=white)](https://h2database.com/)
254256

255257
## Requirements
256258

docs/ai.md

Lines changed: 34 additions & 38 deletions
Large diffs are not rendered by default.

docs/dialects.md

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ Storm works with any JDBC-compatible database using standard SQL. However, datab
99

1010
| | Database | Dialect Package | Key Features |
1111
|---|----------|-----------------|--------------|
12+
| ![Oracle](https://img.shields.io/badge/Oracle-F80000?logo=oracle&logoColor=white) | Oracle | `storm-oracle` | Merge (`MERGE INTO`), sequences |
13+
| ![SQL Server](https://img.shields.io/badge/SQL_Server-CC2927?logo=microsoftsqlserver&logoColor=white) | MS SQL Server | `storm-mssqlserver` | Merge (`MERGE INTO`), identity columns |
1214
| ![PostgreSQL](https://img.shields.io/badge/PostgreSQL-4169E1?logo=postgresql&logoColor=white) | PostgreSQL | `storm-postgresql` | Upsert (`ON CONFLICT`), JSONB, arrays |
1315
| ![MySQL](https://img.shields.io/badge/MySQL-4479A1?logo=mysql&logoColor=white) | MySQL | `storm-mysql` | Upsert (`ON DUPLICATE KEY`), JSON |
1416
| ![MariaDB](https://img.shields.io/badge/MariaDB-003545?logo=mariadb&logoColor=white) | MariaDB | `storm-mariadb` | Upsert (`ON DUPLICATE KEY`), JSON |
15-
| ![Oracle](https://img.shields.io/badge/Oracle-F80000?logo=oracle&logoColor=white) | Oracle | `storm-oracle` | Merge (`MERGE INTO`), sequences |
16-
| ![SQL Server](https://img.shields.io/badge/SQL_Server-CC2927?logo=microsoftsqlserver&logoColor=white) | MS SQL Server | `storm-mssqlserver` | Merge (`MERGE INTO`), identity columns |
17-
| ![H2](https://img.shields.io/badge/H2-0000bb?logoColor=white) | H2 | Built-in | Testing and development (no extra dependency) |
17+
| ![SQLite](https://img.shields.io/badge/SQLite-003B57?logo=sqlite&logoColor=white) | SQLite | `storm-sqlite` | Upsert (`ON CONFLICT`), file-based storage |
18+
| ![H2](https://img.shields.io/badge/H2-0000bb?logoColor=white) | H2 | `storm-h2` | Merge (`MERGE INTO`), sequences, native UUID |
1819

1920
## Installation
2021

@@ -23,6 +24,22 @@ Add the dialect dependency for your database. Dialects are runtime-only dependen
2324
### Maven
2425

2526
```xml
27+
<!-- Oracle -->
28+
<dependency>
29+
<groupId>st.orm</groupId>
30+
<artifactId>storm-oracle</artifactId>
31+
<version>1.11.0</version>
32+
<scope>runtime</scope>
33+
</dependency>
34+
35+
<!-- MS SQL Server -->
36+
<dependency>
37+
<groupId>st.orm</groupId>
38+
<artifactId>storm-mssqlserver</artifactId>
39+
<version>1.11.0</version>
40+
<scope>runtime</scope>
41+
</dependency>
42+
2643
<!-- PostgreSQL -->
2744
<dependency>
2845
<groupId>st.orm</groupId>
@@ -47,18 +64,18 @@ Add the dialect dependency for your database. Dialects are runtime-only dependen
4764
<scope>runtime</scope>
4865
</dependency>
4966

50-
<!-- Oracle -->
67+
<!-- SQLite -->
5168
<dependency>
5269
<groupId>st.orm</groupId>
53-
<artifactId>storm-oracle</artifactId>
70+
<artifactId>storm-sqlite</artifactId>
5471
<version>1.11.0</version>
5572
<scope>runtime</scope>
5673
</dependency>
5774

58-
<!-- MS SQL Server -->
75+
<!-- H2 -->
5976
<dependency>
6077
<groupId>st.orm</groupId>
61-
<artifactId>storm-mssqlserver</artifactId>
78+
<artifactId>storm-h2</artifactId>
6279
<version>1.11.0</version>
6380
<scope>runtime</scope>
6481
</dependency>
@@ -67,6 +84,12 @@ Add the dialect dependency for your database. Dialects are runtime-only dependen
6784
### Gradle (Groovy DSL)
6885

6986
```groovy
87+
// Oracle
88+
runtimeOnly 'st.orm:storm-oracle:1.11.0'
89+
90+
// MS SQL Server
91+
runtimeOnly 'st.orm:storm-mssqlserver:1.11.0'
92+
7093
// PostgreSQL
7194
runtimeOnly 'st.orm:storm-postgresql:1.11.0'
7295
@@ -76,16 +99,22 @@ runtimeOnly 'st.orm:storm-mysql:1.11.0'
7699
// MariaDB
77100
runtimeOnly 'st.orm:storm-mariadb:1.11.0'
78101
79-
// Oracle
80-
runtimeOnly 'st.orm:storm-oracle:1.11.0'
102+
// SQLite
103+
runtimeOnly 'st.orm:storm-sqlite:1.11.0'
81104
82-
// MS SQL Server
83-
runtimeOnly 'st.orm:storm-mssqlserver:1.11.0'
105+
// H2
106+
runtimeOnly 'st.orm:storm-h2:1.11.0'
84107
```
85108

86109
### Gradle (Kotlin DSL)
87110

88111
```kotlin
112+
// Oracle
113+
runtimeOnly("st.orm:storm-oracle:1.11.0")
114+
115+
// MS SQL Server
116+
runtimeOnly("st.orm:storm-mssqlserver:1.11.0")
117+
89118
// PostgreSQL
90119
runtimeOnly("st.orm:storm-postgresql:1.11.0")
91120

@@ -95,11 +124,11 @@ runtimeOnly("st.orm:storm-mysql:1.11.0")
95124
// MariaDB
96125
runtimeOnly("st.orm:storm-mariadb:1.11.0")
97126

98-
// Oracle
99-
runtimeOnly("st.orm:storm-oracle:1.11.0")
127+
// SQLite
128+
runtimeOnly("st.orm:storm-sqlite:1.11.0")
100129

101-
// MS SQL Server
102-
runtimeOnly("st.orm:storm-mssqlserver:1.11.0")
130+
// H2
131+
runtimeOnly("st.orm:storm-h2:1.11.0")
103132
```
104133

105134
## Automatic Detection
@@ -116,11 +145,13 @@ Upsert operations are the primary reason most applications need a dialect. Witho
116145

117146
| Database | SQL Strategy | Conflict Detection |
118147
|----------|--------------|--------------------|
148+
| Oracle | `MERGE INTO ...` | Explicit match conditions |
149+
| MS SQL Server | `MERGE INTO ...` | Explicit match conditions |
119150
| PostgreSQL | `INSERT ... ON CONFLICT DO UPDATE` | Targets a specific unique constraint or index |
120151
| MySQL | `INSERT ... ON DUPLICATE KEY UPDATE` | Primary key or any unique constraint |
121152
| MariaDB | `INSERT ... ON DUPLICATE KEY UPDATE` | Primary key or any unique constraint |
122-
| Oracle | `MERGE INTO ...` | Explicit match conditions |
123-
| MS SQL Server | `MERGE INTO ...` | Explicit match conditions |
153+
| SQLite | `INSERT ... ON CONFLICT DO UPDATE` | Targets a specific unique constraint |
154+
| H2 | `MERGE INTO ...` | Explicit match conditions |
124155

125156
See [Upserts](upserts.md) for usage examples.
126157

@@ -132,23 +163,53 @@ PostgreSQL's JSONB and MySQL/MariaDB's JSON types are fully supported when using
132163

133164
Beyond SQL syntax differences, databases support different native data types. Dialects handle the mapping between Kotlin/Java types and database-specific types automatically, so you can use idiomatic types in your entities without worrying about the underlying storage format.
134165

135-
- **PostgreSQL:** JSONB, UUID, arrays, INET, CIDR
136-
- **MySQL/MariaDB:** JSON, TINYINT for booleans, ENUM
137166
- **Oracle:** NUMBER, CLOB, sequences for ID generation
138167
- **MS SQL Server:** NVARCHAR, UNIQUEIDENTIFIER, IDENTITY
168+
- **PostgreSQL:** JSONB, UUID, arrays, INET, CIDR
169+
- **MySQL/MariaDB:** JSON, TINYINT for booleans, ENUM
170+
- **SQLite:** Dynamic typing, AUTOINCREMENT, file-based storage
171+
- **H2:** Native UUID, sequences, ARRAY types
139172

140173
## Without a Dialect
141174

142-
Storm works without a specific dialect package by generating standard SQL. This is the typical setup during development and testing when using H2 as an in-memory database. The core framework handles entity mapping, queries, joins, transactions, streaming, dirty checking, and caching using only standard SQL. However, some features require database-specific syntax and will be unavailable without a dialect:
175+
Storm works without a specific dialect package by generating standard SQL. The core framework handles entity mapping, queries, joins, transactions, streaming, dirty checking, and caching using only standard SQL. However, some features require database-specific syntax and will be unavailable without a dialect:
143176

144177
- **Upsert operations** require database-specific syntax
145178
- **Database-specific optimizations** such as native pagination strategies
146179

147180
All other features (entity mapping, queries, joins, transactions, streaming, dirty checking, and caching) work identically regardless of dialect.
148181

182+
## Testing with SQLite
183+
184+
SQLite is a lightweight option for testing. It stores data in a single file (or in memory) and requires no server process. Add the `storm-sqlite` dialect dependency to enable SQLite-specific features like upsert support.
185+
186+
<Tabs groupId="language">
187+
<TabItem value="kotlin" label="Kotlin" default>
188+
189+
```kotlin
190+
val dataSource = SQLiteDataSource().apply {
191+
url = "jdbc:sqlite::memory:"
192+
}
193+
val orm = ORMTemplate.of(dataSource)
194+
```
195+
196+
</TabItem>
197+
<TabItem value="java" label="Java">
198+
199+
```java
200+
var dataSource = new SQLiteDataSource();
201+
dataSource.setUrl("jdbc:sqlite::memory:");
202+
var orm = ORMTemplate.of(dataSource);
203+
```
204+
205+
</TabItem>
206+
</Tabs>
207+
208+
Note that SQLite does not support sequences, row-level locking, or `INFORMATION_SCHEMA`. Constraint discovery uses JDBC metadata, and locking relies on SQLite's file-level locking mechanism.
209+
149210
## Testing with H2
150211

151-
H2 is an in-memory Java SQL database that starts instantly and requires no external processes. Storm includes built-in support for H2, making it the default choice for unit tests. Because H2 runs in-process, tests start in milliseconds and do not require Docker, network access, or database installation.
212+
H2 is an in-memory Java SQL database that starts instantly and requires no external processes, making it the default choice for unit tests. Because H2 runs in-process, tests start in milliseconds and do not require Docker, network access, or database installation.
152213

153214
<Tabs groupId="language">
154215
<TabItem value="kotlin" label="Kotlin" default>
@@ -172,7 +233,7 @@ var orm = ORMTemplate.of(dataSource);
172233
</TabItem>
173234
</Tabs>
174235

175-
No additional dialect dependency is needed for H2. This makes it easy to write fast tests that run without Docker or external databases.
236+
For basic testing without upsert support, H2 works without any dialect dependency. To enable upsert support and other H2-specific optimizations (native UUID handling, tuple comparisons), add the `storm-h2` dialect dependency.
176237

177238
## Integration Testing with Real Databases
178239

@@ -187,10 +248,10 @@ mvn test -pl storm-postgresql
187248
## Tips
188249

189250
1. **Always include the dialect** for production databases to unlock all features
190-
2. **Use H2** for unit tests; no additional dialect needed, fast startup
251+
2. **Use H2 or SQLite** for unit tests; add `storm-h2` or `storm-sqlite` for upsert support
191252
3. **Dialect is runtime-only**; it doesn't affect your compile-time code or entity definitions
192253
4. **One dialect per application**; Storm auto-detects the right dialect from your connection URL
193-
5. **Test with both**: Use H2 for fast unit tests and the production dialect for integration tests
254+
5. **Test with both**: Use H2/SQLite for fast unit tests and the production dialect for integration tests
194255

195256
---
196257

docs/getting-started.md

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,71 @@ The framework is organized around three core abstractions:
1818

1919
These abstractions share a common principle: explicit behavior over implicit magic. Every query is visible in the source code. Every relationship is loaded when you ask for it. Every transaction boundary is declared, not inferred. This makes Storm applications straightforward to debug, profile, and reason about.
2020

21-
## How Storm Differs from JPA
21+
## Choose Your Path
2222

23-
If you are coming from JPA/Hibernate, the biggest shift is moving from mutable, proxy-backed entities with a managed lifecycle to stateless, immutable values. Storm has no persistence context, no first-level cache, no `EntityManager`, and no automatic change detection. This eliminates entire categories of bugs (LazyInitializationException, detached entity errors, unexpected flush ordering) while making performance predictable. For a detailed comparison, see the [Migration from JPA](migration-from-jpa.md) guide and the [Storm vs Other Frameworks](comparison.md) feature comparison.
23+
Storm supports two ways to get started. Pick the one that fits your workflow.
2424

25-
## Step-by-Step Setup
25+
import Tabs from '@theme/Tabs';
26+
import TabItem from '@theme/TabItem';
2627

27-
This guide is split into three steps. Follow them in order for the fastest path from zero to a working application.
28+
<Tabs>
29+
<TabItem value="ai" label="AI-Assisted" default>
2830

29-
## 1. Installation
31+
### AI-Assisted Setup
32+
33+
If you use an AI coding tool (Claude Code, Cursor, GitHub Copilot, Windsurf, or Codex), Storm provides rules, skills, and an optional database-aware MCP server that give the AI deep knowledge of Storm's conventions. The AI can generate entities from your schema, write queries, and verify its own work against a real database.
34+
35+
**1. Install the Storm CLI and run it in your project:**
36+
37+
```bash
38+
npx @storm-orm/cli init
39+
```
40+
41+
The interactive setup configures your AI tool with Storm's rules and skills, and optionally connects it to your development database for schema-aware code generation.
42+
43+
**2. Ask your AI tool to set up Storm:**
44+
45+
Once `storm init` has configured your tool, you can ask it to add the right dependencies, create entities from your database tables, and write queries. The AI has access to Storm's full documentation and your database schema.
46+
47+
For example:
48+
- "Add Storm to this project with Spring Boot and PostgreSQL"
49+
- "Create entities for the users and orders tables"
50+
- "Write a repository method that finds orders by status with pagination"
51+
52+
**3. Verify:**
53+
54+
Storm's AI workflow includes built-in verification. The AI can run `ORMTemplate.validateSchema()` to prove entities match the database and `SqlCapture` to inspect generated SQL, all in an isolated H2 test database before anything touches production.
55+
56+
See [AI-Assisted Development](ai.md) for the full setup guide, available skills, and MCP server configuration.
57+
58+
</TabItem>
59+
<TabItem value="manual" label="Manual">
60+
61+
### Manual Setup
62+
63+
Follow these three steps in order for the fastest path from zero to a working application.
64+
65+
**1. Installation**
3066

3167
Set up your project with the right dependencies, build flags, and optional modules.
3268

3369
**[Go to Installation](installation.md)**
3470

35-
## 2. First Entity
71+
**2. First Entity**
3672

3773
Define your first entity, create an ORM template, and perform insert, read, update, and delete operations.
3874

3975
**[Go to First Entity](first-entity.md)**
4076

41-
## 3. First Query
77+
**3. First Query**
4278

4379
Write custom queries, build repositories, stream results, and use the type-safe metamodel.
4480

4581
**[Go to First Query](first-query.md)**
4682

83+
</TabItem>
84+
</Tabs>
85+
4786
---
4887

4988
## What's Next

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ Storm is focused on being a great ORM and SQL template engine. It intentionally
238238

239239
Storm works with any JDBC-compatible database. Dialect packages provide optimized support for:
240240

241-
![PostgreSQL](https://img.shields.io/badge/PostgreSQL-4169E1?logo=postgresql&logoColor=white) ![MySQL](https://img.shields.io/badge/MySQL-4479A1?logo=mysql&logoColor=white) ![MariaDB](https://img.shields.io/badge/MariaDB-003545?logo=mariadb&logoColor=white) ![Oracle](https://img.shields.io/badge/Oracle-F80000?logo=oracle&logoColor=white) ![SQL Server](https://img.shields.io/badge/SQL_Server-CC2927?logo=microsoftsqlserver&logoColor=white) ![H2](https://img.shields.io/badge/H2-0000bb?logoColor=white)
241+
![Oracle](https://img.shields.io/badge/Oracle-F80000?logo=oracle&logoColor=white) ![SQL Server](https://img.shields.io/badge/SQL_Server-CC2927?logo=microsoftsqlserver&logoColor=white) ![PostgreSQL](https://img.shields.io/badge/PostgreSQL-4169E1?logo=postgresql&logoColor=white) ![MySQL](https://img.shields.io/badge/MySQL-4479A1?logo=mysql&logoColor=white) ![MariaDB](https://img.shields.io/badge/MariaDB-003545?logo=mariadb&logoColor=white) ![SQLite](https://img.shields.io/badge/SQLite-003B57?logo=sqlite&logoColor=white) ![H2](https://img.shields.io/badge/H2-0000bb?logoColor=white)
242242

243243
See [Database Dialects](dialects.md) for installation and configuration details.
244244

docs/installation.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,11 +155,13 @@ Storm works with any JDBC-compatible database out of the box. Dialect modules pr
155155

156156
| Module | Database |
157157
|--------|----------|
158+
| `storm-oracle` | Oracle |
159+
| `storm-mssqlserver` | SQL Server |
158160
| `storm-postgresql` | PostgreSQL |
159161
| `storm-mysql` | MySQL |
160162
| `storm-mariadb` | MariaDB |
161-
| `storm-oracle` | Oracle |
162-
| `storm-mssqlserver` | SQL Server |
163+
| `storm-sqlite` | SQLite |
164+
| `storm-h2` | H2 |
163165

164166
```kotlin
165167
runtimeOnly("st.orm:storm-postgresql")
@@ -212,7 +214,7 @@ storm-foundation (base interfaces)
212214
└── storm-kotlin / storm-java21 (your primary dependency)
213215
├── storm-kotlin-spring / storm-spring (Spring Framework)
214216
│ └── storm-kotlin-spring-boot-starter / storm-spring-boot-starter
215-
├── dialect modules (postgresql, mysql, mariadb, oracle, mssqlserver)
217+
├── dialect modules (postgresql, mysql, mariadb, oracle, mssqlserver, sqlite, h2)
216218
└── JSON modules (jackson2, jackson3, kotlinx-serialization)
217219
```
218220

0 commit comments

Comments
 (0)