Files
Flash5/flash-extensions/flash-ext-data-jdbc/docs/README.md
T
Zakaria El OrcheandClaude Opus 5 c5179146c0 docs(data): write the data-layer docs in English
The three data modules' docs were in Italian, so the synchronization contract
added in the previous commit went in as Italian too, to match its file. English
is the project's language for docs, comments and READMEs alike, and a file half
in each is worse than either — so all three are translated, not just the new
section.

Content is otherwise unchanged, except the "synchronizations run on
commit/rollback" line in the two backend READMEs, which was vague before and is
now accurate about which hook sees the session/connection still bound, pointing
at flash-ext-data-core's README for the full contract.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-12 23:36:11 +00:00

2.9 KiB

flash-ext-data-jdbc

JDBC backend for flash-ext-data-core.

Purpose

This module implements TxManager on top of a DataSource and provides a raw-SQL repository base class.

How to use it

1. Create the manager

DataSource dataSource = ...;
JdbcTxManager txManager = new JdbcTxManager(dataSource);
DataExtension extension = new DataExtension(txManager);

2. Install the extension in Flash

As with Hibernate, DataExtension registers Tx in the FlashContext and enables @Transactional on class-based handlers.

3. Define a repository

public final class UserRepository extends JdbcRepository<User, Long> {
    public UserRepository(Tx tx) {
        super(tx, "users", "id");
    }

    @Override
    protected User mapRow(ResultSet rs) throws SQLException {
        return new User(rs.getLong("id"), rs.getString("name"));
    }
}

Here too you can expose reusable Specs and compose queries from the service layer:

public final class UserRepository extends JdbcRepository<User, Long> {
    public static final SpecBuilder.FieldSpec<User, String> EMAIL = SpecBuilder.field("email");

    public UserRepository(Tx tx) {
        super(tx, "users", "id");
    }
}

Saving and updating need an explicit binding:

@Override
protected String insertSql() {
    return "insert into users(name) values(?)";
}

@Override
protected void bindInsert(PreparedStatement ps, User entity) throws SQLException {
    ps.setString(1, entity.name());
}

How it works underneath

  • The current transaction exposes a Connection.
  • Tx.resource(Connection.class) retrieves the connection bound to the thread.
  • REQUIRES_NEW suspends the active connection and opens a new one.
  • NOT_SUPPORTED suspends the context and continues without a transaction.

Repository base class

JdbcRepository provides:

  • select queries through queryOne, queryMany
  • mutations through mutate
  • persistence through doSave, doUpdate
  • paging through doFindPage
  • bulk deleteAll(Spec<T>)
  • raw helpers queryOne(...), queryMany(...), mutate(...)

Concrete repositories only have to translate between ResultSet and the domain.

Transactional semantics

  • REQUIRED: join, or open a new transaction.
  • REQUIRES_NEW: suspend the current context.
  • SUPPORTS: join if a transaction exists, otherwise no-op.
  • NOT_SUPPORTED: suspend and continue without a transaction.
  • MANDATORY: fail if there is no transaction.

Notes

  • The Connection is closed when a new transaction ends.
  • Synchronizations registered in a transaction fire when that transaction completes: beforeCommit while it is still active and the Connection still bound, the post-completion hooks once it is unbound. See flash-ext-data-core/docs/README.md for the full contract.
  • If a repository uses doDelete(T), the default behaviour is unsupported: use deleteById or override it.