Use Spring Data read models
Add an integration
Section titled “Add an integration”Start with the store your application already uses. Choose the JPA integration for a relational store or the MongoDB integration for MongoDB; you do not need both to use a repository:
// JPAdependencies { implementation("io.cratis:arc-spring-data-jpa:<version>")}// MongoDBdependencies { implementation("io.cratis:arc-spring-data-mongodb:<version>")}Each module includes the Arc Spring Boot starter and the corresponding Spring Data starter. Configure the chosen store through Spring Boot as usual: it still owns the datasource, entity manager, Mongo client, repository discovery, and their standard configuration.
Inject a repository into a query
Section titled “Inject a repository into a query”Once Spring has discovered the application’s repository, use it as an ordinary Spring service. In a model-bound query, mark the repository parameter with @FromServices. Arc’s generated performer then obtains that dependency from the current application context rather than treating it as caller input.
@Entity@ReadModelpublic class TaskView { @Id public String id; public String title;
public static List<TaskView> all(@FromServices TaskViewRepository tasks) { return tasks.findAll(); }}
interface TaskViewRepository extends JpaRepository<TaskView, String> { }@Entity@ReadModeldata class TaskView(@Id val id: String = "", val title: String = "") { companion object { @JvmStatic fun all(@FromServices tasks: TaskViewRepository): List<TaskView> = tasks.findAll() }}
interface TaskViewRepository : JpaRepository<TaskView, String>In the example, the query calls the injected repository and returns its results. The Kotlin companion method and Java static method expose the same read operation; neither creates the repository or configures its store.
The same injection pattern works with MongoRepository, repository fragments, and application query services. An application bean replaces an auto-configured adapter bean of the same integration contract. Repository injection alone does not select a tenant’s storage or subscribe to changes.
Continue with the operation you need. Concept mapping is an optional branch for the chosen store, not a requirement to configure both integrations:
- Repositories in queries and commands — consume paging, resolve a command’s current state, choose tenant-bound access, and opt into supported transactions.
- Map JPA concepts — use attribute converters and embedded ids when a JPA model stores domain concepts.
- Map MongoDB concepts — register concrete scalar pairs and identifier mappings when a MongoDB document stores domain concepts.
- Observable storage snapshots — return replacement query results as storage changes, using MongoDB change streams or explicit JPA notifications.