Data Persistence
|
This section documents the current Vaadin release line — Vaadin 24 LTS / 25.x, Java 17+, Spring Boot 3 / Jakarta EE 10 — as published at the official Vaadin documentation, which is the reference these pages are written and verified against. No specific patch version is pinned. Flow (server-side Java) is the authoring style used throughout, with Hilla / React shown where it differs; Vaadin 7 and the pre-Flow architecture appear only as migration contrast. This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, since Vaadin ships major releases roughly twice a year and its ecosystem iterates. This section’s bibliography lists the reference material consulted while preparing these pages. |
A Vaadin view holds no persistence code of its own — it calls a service, which uses whatever data-access
stack the project already has. This page follows
the Persistence guide and shows the two
Vaadin-specific concerns: feeding a lazy Grid from the database, and the transaction boundary. For SQL and
schema design, see the SQL Reference; for document stores,
the MongoDB Reference.
Choosing a stack
| Option | Fits |
|---|---|
Spring Data JPA |
The default. Repositories, derived queries, |
jOOQ |
Typed SQL DSL generated from the schema; full control over queries, no ORM surprises. |
Flyway |
Versioned schema migrations; runs on startup, independent of the query stack. |
Flyway migrations live under src/main/resources/db/migration:
-- V1__create_customer.sql
CREATE TABLE customer (
id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(200) NOT NULL,
email VARCHAR(320) NOT NULL UNIQUE
);
A lazy Grid over a repository
Extend PagingAndSortingRepository (or JpaRepository), then translate the Grid’s Query into a Spring
Pageable. VaadinSpringDataHelpers does the sort mapping:
public interface CustomerRepository
extends JpaRepository<Customer, Long>,
JpaSpecificationExecutor<Customer> { }
@Service
public class CustomerService {
private final CustomerRepository repo;
public CustomerService(CustomerRepository repo) { this.repo = repo; }
public Page<Customer> list(Pageable pageable, String filter) {
return repo.findByNameContainingIgnoreCase(
filter == null ? "" : filter, pageable);
}
}
// in the view
grid.setItems(
query -> service.list(
VaadinSpringDataHelpers.toSpringPageRequest(query),
filterField.getValue()).stream(),
query -> (int) service.list(
VaadinSpringDataHelpers.toSpringPageRequest(query),
filterField.getValue()).getTotalElements());
Now paging, sorting and filtering all execute in the database; the server never holds more than one page. See The Grid Component for the Grid side and Spring Data JPA.
jOOQ
public List<Customer> search(String term, int offset, int limit) {
return dsl.selectFrom(CUSTOMER)
.where(CUSTOMER.NAME.likeIgnoreCase("%" + term + "%"))
.orderBy(CUSTOMER.NAME)
.offset(offset).limit(limit)
.fetchInto(Customer.class);
}
The same fetch(offset, limit) / count() pair feeds grid.setItems(…).
The transaction boundary
A Flow view runs outside any transaction. Keep persistence work inside @Transactional service methods and
return fully-initialised objects (or DTOs) — touching a lazy JPA association from the view thread throws
LazyInitializationException:
@Transactional(readOnly = true)
public CustomerDetails load(Long id) {
Customer c = repo.findById(id).orElseThrow();
c.getOrders().size(); // force-initialise inside the transaction
return CustomerDetails.from(c);
}
Prefer projections / DTOs over spring.jpa.open-in-view=true, which keeps a session open for the whole request
and hides the problem. A write goes through its own @Transactional method; concurrent edits are handled with
a JPA @Version column (see Forms, CRUD and Master-Detail).
Refreshing after a write
The Grid does not know the database changed. After a save or delete, refresh the data view:
service.save(edited);
grid.getDataProvider().refreshAll(); // re-fetch visible rows
// or, for an in-place edit:
grid.getDataProvider().refreshItem(edited);
See also
-
The Grid Component — the
DataProviderand lazyGridthese callbacks drive. -
Spring Boot Integration and Jakarta EE and CDI — the two DI stacks and their
@Transactional/@Statelessboundaries. -
Forms, CRUD and Master-Detail — optimistic locking on concurrent edits.
-
SQL Reference and MongoDB Reference — the data stores themselves.
-
Persistence — the official guide.