在本教程中,我们将学习如何为类配置 MongoDB 集合名称,并通过实际案例演示实现方法。我们将使用 Spring Data,它提供了多种轻量级配置选项。通过构建一个简单的音乐商店应用,我们将探索每种配置方式的适用场景。
2. 用例与项目设置
我们的用例包含四个核心类:MusicAlbum、Compilation、MusicTrack 和 Store。每个类将采用不同方式配置集合名称,且每个类都有对应的 MongoRepository。无需自定义查询,只需准备一个配置好的 MongoDB 实例。
2.1. 按名称列出集合内容的控制器
首先编写一个控制器验证配置是否生效。我们将通过集合名称进行查询。注意使用 Repository 时,集合名称配置是透明的:
@RestController
@RequestMapping("/collection")
public class CollectionController {
@Autowired
private MongoTemplate mongoDb;
@GetMapping("/{name}")
public List<DBObject> get(@PathVariable String name) {
return mongoDb.findAll(DBObject.class, name);
}
}
该控制器基于 MongoTemplate,使用通用类型 DBObject,不依赖具体类和 Repository。这样能直接查看 MongoDB 内部属性,特别是 Spring Data 用于反序列化的 "_class" 属性,确保配置正确。
2.2. API 服务层
接下来构建服务层,实现对象保存和集合查询功能。Compilation 类将在第一个配置示例中创建:
@Service
public class MusicStoreService {
@Autowired
private CompilationRepository compilationRepository;
public Compilation add(Compilation item) {
return compilationRepository.save(item);
}
public List<Compilation> getCompilationList() {
return compilationRepository.findAll();
}
// 其他服务方法
}
2.3. API 接口层
最后编写控制器暴露服务接口:
@RestController
@RequestMapping("/music")
public class MusicStoreController {
@Autowired
private MusicStoreService service;
@PostMapping("/compilation")
public Compilation post(@RequestBody Compilation item) {
return service.add(item);
}
@GetMapping("/compilation")
public List<Compilation> getCompilationList() {
return service.getCompilationList();
}
// 其他接口方法
}
现在开始配置各个类。
3. 使用 @Document 注解配置
Spring Data 1.9 版本引入的 @Document 注解能满足所有配置需求。它专用于 MongoDB,类似 JPA 的 @Entity 注解。目前无法为集合名称定义命名策略(仅字段名支持),下面探索可用方案。
3.1. 默认行为
默认行为将类名首字母小写作为集合名。只需添加 @Document 注解即可生效:
@Document
public class Compilation {
@Id
private String id;
// getters and setters
}
所有通过 Compilation Repository 插入的数据将存入 MongoDB 的 "compilation" 集合:
$ curl -X POST http://localhost:8080/music/compilation -H 'Content-Type: application/json' -d '{
"name": "Spring Hits"
}'
{ "id": "6272e26e04a673360d926ca1" }
查询 "compilation" 集合验证配置:
$ curl http://localhost:8080/collection/compilation
[
{
"name": "Spring Hits",
"_class": "com.baeldung.boot.collection.name.data.Compilation"
}
]
这是最简洁的配置方式,缺点是若修改数据库命名规范(如改用下划线命名),需重构所有类。
3.2. 覆盖 value 属性
通过 @Document 的 collection 属性可覆盖默认行为。由于 value 是其别名,可直接设置:
@Document("albums")
public class MusicAlbum {
@Id
private String id;
private String name;
private String artist;
// getters and setters
}
现在数据将存入 "albums" 而非 "musicAlbum" 集合。这是 Spring Data 中最简单的自定义集合名方式。添加专辑测试:
$ curl -X POST 'http://localhost:8080/music/album' -H 'Content-Type: application/json' -d '{
"name": "Album 1",
"artist": "Artist A"
}'
{ "id": "62740de003d2452a61a75c35" }
查询 "albums" 集合验证:
$ curl 'http://localhost:8080/collection/albums'
[
{
"name": "Album 1",
"artist": "Artist A",
"_class": "com.baeldung.boot.collection.name.data.MusicAlbum"
}
]
此方式适合适配现有数据库(集合名与类名不匹配),缺点是无法统一添加前缀。
3.3. 结合配置属性与 SpEL
此组合能实现 @Document 单独无法完成的功能。首先定义应用级属性供多个类复用。
在 application.properties 添加集合名后缀属性:
collection.suffix=db
通过 SpEL 引用 environment bean 创建类:
@Document("store-#{@environment.getProperty('collection.suffix')}")
public class Store {
@Id
private String id;
private String name;
// getters and setters
}
创建商店测试:
$ curl -X POST 'http://localhost:8080/music/store' -H 'Content-Type: application/json' -d '{
"name": "Store A"
}'
{ "id": "62744c6267d3a034ec5e5719" }
数据存入 "store-db" 集合,查询验证:
$ curl 'http://localhost:8080/collection/store-db'
[
{
"name": "Store A",
"_class": "com.baeldung.boot.collection.name.data.Store"
}
]
修改后缀只需更新配置文件,缺点是模板代码较多。此方式也支持多租户场景(如用租户 ID 替代后缀区分非共享集合)。
3.4. 结合 Bean 方法与 SpEL
SpEL 的另一缺点是需额外编程处理,但能调用任意 Bean 方法动态确定集合名。接下来创建 Bean 实现命名规则转换。
采用下划线命名策略,借用 Spring Data 的 SnakeCaseFieldNamingStrategy 创建工具 Bean:
public class Naming {
public String fix(String name) {
List<String> parts = ParsingUtils.splitCamelCaseToLower(name);
List<String> result = new ArrayList<>();
for (String part : parts) {
if (StringUtils.hasText(part)) {
result.add(part);
}
}
return StringUtils.collectionToDelimitedString(result, "_");
}
}
将 Bean 添加到应用:
@SpringBootApplication
public class SpringBootCollectionNameApplication {
// main method
@Bean
public Naming naming() {
return new Naming();
}
}
通过 SpEL 引用该 Bean:
@Document("#{@naming.fix('MusicTrack')}")
public class MusicTrack {
@Id
private String id;
private String name;
private String artist;
// getters and setters
}
添加曲目测试:
$ curl -X POST 'http://localhost:8080/music/track' -H 'Content-Type: application/json' -d '{
"name": "Track 1",
"artist":"Artist A"
}'
{ "id": "62755987ae94c5278b9530cc" }
数据存入 "music_track" 集合:
$ curl 'http://localhost:8080/collection/music_track'
[
{
"name": "Track 1",
"artist": "Artist A",
"_class": "com.baeldung.boot.collection.name.data.MusicTrack"
}
]
缺点是无法动态获取类名,但优势是修改命名规则时无需手动重命名所有类。
4. 总结
本文探讨了使用 Spring Data 工具配置集合名称的多种方式。我们分析了每种方案的优缺点,以便根据具体场景选择最佳方案。通过构建音乐商店用例,展示了不同配置方法的实际应用。
完整源码可在 GitHub 获取。