Skip to content

Commit f1119c9

Browse files
authored
Feature/storm 82 2 (#89)
Add documentation. (#82)
1 parent bdf4c6a commit f1119c9

4 files changed

Lines changed: 39 additions & 21 deletions

File tree

docs/comparison.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,26 @@ Exposed is JetBrains' official Kotlin database framework. It offers two APIs: a
233233
| **Type Safety** | Column references | Metamodel DSL |
234234
| **Transactions** | Required `transaction {}` block | Optional, programmatic + declarative |
235235

236+
#### Transaction Propagation
237+
238+
Both Storm and Exposed use a `transaction { }` block for programmatic transaction management, but they differ significantly in propagation support.
239+
240+
Exposed's native API supports two modes: shared nesting (the default, where inner blocks join the outer transaction) and savepoint-based nesting (via `useNestedTransactions = true`). For other propagation behaviors, Exposed relies on Spring's `@Transactional` through its `SpringTransactionManager` integration module.
241+
242+
Storm supports all seven standard propagation modes natively in its `transaction { }` block, without requiring Spring:
243+
244+
| Propagation | Storm | Exposed |
245+
|-------------|-------|---------|
246+
| `REQUIRED` | Yes | Yes (default behavior) |
247+
| `REQUIRES_NEW` | Yes | No (Spring only) |
248+
| `NESTED` | Yes | Yes (`useNestedTransactions`) |
249+
| `MANDATORY` | Yes | No |
250+
| `SUPPORTS` | Yes | No |
251+
| `NOT_SUPPORTED` | Yes | No |
252+
| `NEVER` | Yes | No |
253+
254+
This means Storm's programmatic API can express patterns like audit logging (`REQUIRES_NEW`), defensive boundary enforcement (`MANDATORY`, `NEVER`), and non-transactional operations (`NOT_SUPPORTED`) directly in code, while Exposed requires Spring integration for these use cases. See [Transactions](transactions.md) for details and examples of each propagation mode.
255+
236256
### When to Choose Storm
237257

238258
- You need Kotlin and Java support

docs/sql-templates.md

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -341,40 +341,36 @@ When working with subqueries or nested template expressions, you may need to con
341341
| `INNER` | Resolve only within the current (innermost) scope. Fails if the alias is not defined locally. |
342342
| `OUTER` | Resolve only from outer scope(s), ignoring locally defined aliases. |
343343

344-
The `alias()` and `column()` template functions accept an optional `ResolveScope` parameter:
344+
The `alias()` and `column()` template functions accept an optional `ResolveScope` parameter. This is most useful in correlated subqueries where the same entity appears in both the outer and inner query. For example, selecting all pets that have at least one visit:
345345

346346
<Tabs groupId="language">
347347
<TabItem value="kotlin" label="Kotlin" default>
348348

349349
```kotlin
350-
orm.query { """
351-
SELECT ${User::class}
352-
FROM ${User::class}
353-
WHERE ${User_.id} IN (
354-
SELECT ${column(Order_.userId, ResolveScope.INNER)}
355-
FROM ${table(Order::class)}
356-
WHERE ${column(Order_.total, ResolveScope.INNER)} > ${1000}
357-
)
358-
""" }
350+
val pets = orm.entity(Pet::class)
351+
.select()
352+
.whereExists { subquery(Visit::class)
353+
.where { "${column(Visit_.pet, INNER)} = ${column(Pet_.id, OUTER)}" }
354+
}
355+
.resultList
359356
```
360357

361358
</TabItem>
362359
<TabItem value="java" label="Java">
363360

364361
```java
365-
orm.query(RAW."""
366-
SELECT \{User.class}
367-
FROM \{User.class}
368-
WHERE \{User_.id} IN (
369-
SELECT \{column(Order_.userId, ResolveScope.INNER)}
370-
FROM \{table(Order.class)}
371-
WHERE \{column(Order_.total, ResolveScope.INNER)} > \{1000}
372-
)""")
362+
var pets = orm.entity(Pet.class).select()
363+
.where(wb -> wb.exists(
364+
wb.subquery(Visit.class)
365+
.where(RAW."\{column(Visit_.pet, INNER)} = \{column(Pet_.id, OUTER)}")))
366+
.getResultList();
373367
```
374368

375369
</TabItem>
376370
</Tabs>
377371

372+
The `column()` function with a metamodel reference resolves to the fully qualified column name (e.g., `v.pet_id` and `p.id`). `INNER` tells Storm to resolve `Visit_.pet` from the subquery, while `OUTER` resolves `Pet_.id` from the main query.
373+
378374
In most cases the default `CASCADE` scope is correct, because it ensures that each alias resolves to exactly one table. Use `INNER` or `OUTER` when writing correlated subqueries where you need to control whether a reference resolves to the inner query's tables or the outer query's tables.
379375

380376
---

docs/transactions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Storm works directly with JDBC transactions and supports both programmatic and d
1414

1515
Storm for Kotlin provides a fully programmatic transaction solution (following the style popularized by [Exposed](https://github.com/JetBrains/Exposed)) that is **completely coroutine-friendly**. It supports **all isolation levels and propagation modes** found in traditional transaction management systems. You can freely switch coroutine dispatchers within a transaction (offload CPU-bound work to `Dispatchers.Default` or IO work to `Dispatchers.IO`) and still remain in the **same active transaction**.
1616

17+
While Storm's `transaction { }` blocks look similar to Exposed's, Storm goes further by supporting all seven standard propagation modes (`REQUIRED`, `REQUIRES_NEW`, `NESTED`, `MANDATORY`, `SUPPORTS`, `NOT_SUPPORTED`, `NEVER`). Exposed's native transaction API only supports basic nesting (shared transaction) and savepoint-based nesting (`useNestedTransactions = true`), without the ability to suspend an outer transaction, enforce transactional context, or run non-transactionally. See [Storm vs Exposed](comparison.md#storm-vs-exposed) for a detailed comparison.
18+
1719
The API is designed around Kotlin's type system and coroutine model. Import the transaction functions and enums from `st.orm.template`:
1820

1921
```kotlin

website/sidebars.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ const sidebars: SidebarsConfig = {
2929
type: 'category',
3030
label: 'Entity Modeling',
3131
items: [
32-
'polymorphism',
3332
'converters',
34-
'entity-lifecycle',
35-
'validation',
3633
'json',
34+
'polymorphism',
35+
'entity-lifecycle',
3736
'serialization',
37+
'validation',
3838
],
3939
},
4040
{

0 commit comments

Comments
 (0)