示例工程【免费下载链接】spring-data-examplesSpring Data Example Projects项目地址https://gitcode.com/gh_mirrors/sp/spring-data-examples点击查看免费下载本指南以 spring-data-examples 仓库中的multi-store示例为骨架讲解在一个应用内同时启用 Spring Data JPA 与 Spring Data MongoDB 两个模块时Spring Data 如何识别当前仓库接口到底该交给哪个存储模块这一核心问题。读完本文你将掌握多存储应用下仓库自动检测repository auto-detection的严格配置模式strict repository configuration mode、Entity/Document注解驱动的分配规则以及如何用测试验证仓库被正确分配给了对应的存储。背景为什么多存储应用需要更严格的仓库检测Spring Data 的仓库抽象允许开发者只写接口如CrudRepository而不写实现类。当应用只使用一个 Spring Data 模块时检测逻辑非常简单扫描到仓库接口就注册。但当应用同时引入多个 Spring Data 模块例如 JPA MongoDB时同一个仓库接口可能被多个模块都看着像自己该管的此时就需要一个明确的判定规则。正如 multi-store/README.md 开头所述This sample shows a project working with multiple Spring Data modules and how the repository auto-detection has become stricter with the Evans release train.也就是说从Evans版本系列Spring Data 的 release train 代号开始仓库自动检测行为变得更加严格一旦 Spring Data 检测到应用同时运行在多个 Spring Data 模块之上就会进入strict repository configuration mode严格仓库配置模式在此模式下只有能够被唯一分配给当前扫描模块的仓库接口才会被注册。示例工程结构一览multi-store模块本身是一个 Maven 子工程见根 pom.xml 中的modules列表其目录结构如下multi-store/ ├── pom.xml └── src/ ├── main/java/example/springdata/multistore/ │ ├── ApplicationConfiguration.java │ ├── customer/ (Address.java, Customer.java, CustomerRepository.java) │ └── shop/ (LineItem.java, Order.java, OrderRepository.java) └── test/java/example/springdata/multistore/ └── ApplicationConfigurationTest.java工程只有两个领域域store domaincustomer 域走 JPA关系型数据库测试时用 HSQLDB 内嵌库shop 域走 MongoDB测试时用 Testcontainers 启动真实 MongoDB 容器整个应用只需一个带SpringBootApplication的配置类即可完成装配ApplicationConfiguration.java 中没有任何显式的EnableJpaRepositories/EnableMongoRepositories声明——两个模块的仓库扫描全部由 Spring Boot 自动配置完成这正是仓库自动检测机制发挥作用的场景。两个存储域用注解标记归属严格模式下仓库接口的归属判断靠的是被管理的领域类型managed domain type上的存储专属注解。示例中恰好两个域各用了一个典型注解JPA 域Customer.java 用jakarta.persistence.Entity标注主键为Id GeneratedValue Long idData Entity public class Customer { private Id GeneratedValue Long id; private String firstname, lastname; private Address address; public Customer(String firstname, String lastname) { Assert.hasText(firstname, Firstname must not be null or empty!); Assert.hasText(lastname, Lastname must not be null or empty!); this.firstname firstname; this.lastname lastname; } // Required by JPA protected Customer() {} }其仓库接口 CustomerRepository.java 继承CrudRepositoryCustomer, Long完全交给 JPA 模块实现。MongoDB 域Order.java 用org.springframework.data.mongodb.core.mapping.Document标注Data RequiredArgsConstructor(onConstructor __(PersistenceCreator)) Document public class Order { private final String id; private final String customerId; private final Date orderDate; private final ListLineItem items; // ... }其仓库接口 OrderRepository.java 继承CrudRepositoryOrder, String。值得一提的细节是 Order.java 的类注释Note how we dont need any MongoDB mapping annotations asidis recognized as the id property by default.即 MongoDB 侧只需Documentid字段会被默认识别为文档主键无需额外映射注解。同理Address.java 用Embeddable作为 JPA 内嵌值对象嵌入Customer。核心机制严格仓库配置模式的运行日志multi-store模块的 ApplicationConfigurationTest.java 是一个SpringBootTest集成测试README 明确说明运行该测试即可在 DEBUG 日志中看到严格模式被激活的完整过程。原文档给出的日志如下… DEBUG … - Multiple Spring Data modules found, entering strict repository configuration mode! … … DEBUG … - Spring Data JPA - Could not safely identify store assignment for repository candidate interface example.springdata.multistore.shop.OrderRepository. … DEBUG … - Spring Data JPA - Registering repository: customerRepository - Interface: example.springdata.multistore.customer.CustomerRepository - Factory: org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean … DEBUG … - Multiple Spring Data modules found, entering strict repository configuration mode! … … DEBUG … - Spring Data MongoDB - Could not safely identify store assignment for repository candidate interface example.springdata.multistore.customer.CustomerRepository. … DEBUG … - Spring Data MongoDB - Registering repository: orderRepository - Interface: example.springdata.multistore.shop.OrderRepository - Factory: org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean这段日志非常直观地展示了严格模式的两阶段判定触发Spring Data 发现应用同时存在多个 Spring Data 模块随即打印Multiple Spring Data modules found, entering strict repository configuration mode!并切换到严格模式。逐模块扫描与交叉排除当Spring Data JPA扫描时遇到OrderRepository其领域类型Order带有DocumentJPA 无法安全地确认这是自己的仓库于是打印Could not safely identify store assignment for repository candidate interface ... OrderRepository并跳过同时成功注册CustomerRepository领域类型带Entity工厂类为org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean。当Spring Data MongoDB扫描时对称地跳过CustomerRepository成功注册OrderRepository工厂类为org.springframework.data.mongodb.repository.support.MongoRepositoryFactoryBean。这正是 README 所总结的默认判定规则By default this assignment is detected by inspecting the managed domain type for store specific annotations (e.g.Entityfor JPA orDocumentfor MongoDB).也就是说Could not safely identify store assignment 并不是报错而是严格模式下的正常现象——各模块在交叉扫描到不属于自己的仓库接口时主动让位从而保证每个仓库接口最终被唯一分配到一个存储模块避免同一个接口被两个模块重复实例化造成歧义。用断言验证仓库归属Repositories API严格模式是否真的把仓库分配给了正确的存储测试用RepositoriesAPI 给出了可验证的结论。核心断言位于 ApplicationConfigurationTest.javaTest void repositoriesAreAssignedToAppropriateStores() { var repositories new Repositories(context); assertThat(repositories.getEntityInformationFor(Customer.class)).isInstanceOf(JpaEntityInformation.class); assertThat(repositories.getEntityInformationFor(Order.class)).isInstanceOf(MongoEntityInformation.class); }这里通过org.springframework.data.repository.support.Repositories从ApplicationContext中检索每个领域类型对应的EntityInformationCustomer的实体信息是org.springframework.data.jpa.repository.support.JpaEntityInformationJPA 侧Order的实体信息是org.springframework.data.mongodb.repository.query.MongoEntityInformationMongoDB 侧。由此可以从运行时证据上确认仓库自动检测确实把两个仓库接口分别分配给了 JPA 与 MongoDB 两个模块。该测试还演示了多存储应用测试环境的搭建——通过TestConfiguration配合 Testcontainers 启动 MongoDB 容器TestConfiguration static class Infrastructure { Bean ServiceConnection MongoDBContainer mongoDBContainer() { return new MongoDBContainer(DockerImageName.parse(mongodb/mongodb-community-server)); } }ServiceConnection是 Spring Boot 的测试特性容器启动后其连接信息会自动配置到应用的 MongoDB 连接中测试类无需手写任何连接参数。JPA 侧则使用 HSQLDB 内嵌数据库test 作用域因此运行该测试的前提是本机安装有 Docker用于启动 MongoDB 容器。依赖配置同时引入两个 Starter多存储应用的依赖装配体现在 multi-store/pom.xml 中核心依赖只有两个 Starterdependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-mongodb/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId /dependency配套的测试依赖包括org.hsqldb:hsqldbtest 作用域JPA 侧内嵌库与org.testcontainers:testcontainers-mongodbtest 作用域MongoDB 侧容器。整个工程继承仓库根 pom.xml当前基于 Spring Boot 4.0.4、Java 25 编译级别因此两个 Starter 的版本号由父 POM 统一管理无需显式书写。运行方式在仓库根目录执行./mvnw -pl multi-store test或在multi-store目录下执行../mvnw test即可运行ApplicationConfigurationTest并观察到上文所述的严格模式 DEBUG 日志。延伸阅读Spring Data REST 视角下的多存储实践仓库中还提供了另一个同主题示例rest/multi-store见根 README.adoc 中 A sample REST web-service based on both Spring Data JPA and Spring Data MongoDB 的说明它把同样的 JPA MongoDB 双存储组合放在了 Spring Data REST 场景下Person.java 用Entity标注走 JPAH2 内嵌库Treasure.java 用Document标注走 MongoDBApplication.java 同样是极简的SpringBootApplicationApplicationIntegrationTests.java 中直接Autowired注入PersonRepository与TreasureRepository同时向两个存储写入数据并遍历读取从使用层面演示了双存储仓库的开箱即用。该示例的 pom.xml 依赖模式与multi-store一致JPA MongoDB 两个 Starter、H2、testcontainers-mongodb可作为把多存储能力暴露为 REST 服务时的参考模板。实践要点小结严格模式由多个 Spring Data 模块共存自动触发无需任何显式配置触发后日志中会出现Multiple Spring Data modules found, entering strict repository configuration mode!。仓库归属默认由领域类型上的存储专属注解决定JPA 看EntityMongoDB 看Document。若领域类型没有任何可识别的存储注解例如纯 POJO 被多个模块扫描到就会出现 Could not safely identify store assignment 并被跳过——这是设计行为而非故障。保持领域类型与仓库一一对应确保每个仓库接口的领域类型带有且仅带有目标存储的注解是让自动检测稳定工作的前提。用RepositoriesAPI 做运行时验证像ApplicationConfigurationTest那样断言EntityInformation的具体实现类可以在 CI 中持续保证仓库分配的 correctness。测试环境依赖 DockerMongoDB 侧通过 Testcontainers 容器提供真实存储运行集成测试前需确保 Docker 可用。赞分享示例工程【免费下载链接】spring-data-examplesSpring Data Example Projects项目地址https://gitcode.com/gh_mirrors/sp/spring-data-examples点击查看免费下载相关推荐Spring Data多数据源配置JPA与MongoDB混合存储终极指南 Spring Data多数据源配置JPA与MongoDB混合存储终极指南 在现代企业级应用开发中如何高效配置和管理 Spring Data多数据源 成示例工程Noname 移动端Capacitor Android SAF构建与文件系统覆盖层实战指南Noname 移动端Capacitor Android SAF构建与文件系统覆盖层实战指南 Noname无名杀的移动端采用 Capacitor 封装示例工程Spring Data JPA 多数据源实战手动装配 CustomerConfig 与 OrderConfig 隔离两个独立数据库Spring Data JPA 多数据源实战手动装配 CustomerConfig 与 OrderConfig 隔离两个独立数据库 本指南以 spring d示例工程上一篇CangjieMagic 模型管理指南ModelConfig、ModelManager 与 ModelUtils 实战解析下一篇【亲测免费】 开源项目推荐Open Source Report Card (OSRC)创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考