Azure Cosmos DB:Spring+Java实现存储过程不存在时再注册
解决方案:仅当存储过程不存在时创建
问题原因
每次应用重启时直接调用createStoredProcedure方法,不管目标存储过程是否已存在,而Azure Cosmos DB不允许创建ID重复的存储过程,因此触发资源已存在的错误。
修改后的实现逻辑
在创建存储过程前,先检查指定ID的存储过程是否存在:
- 若不存在,执行创建操作
- 若已存在,直接返回已有的存储过程(或可选更新内容)
修改后的代码示例
@Configuration public class StoredProcConfig { @Autowired @Qualifier(BeansConstants.PAYMENT_CONTAINER) CosmosContainer container; @Bean public CosmosStoredProcedureResponse registerSp() throws IOException { String spId = "spCreateToDoItems"; // 读取存储过程JS文件内容 InputStream is = getFileFromResourceAsStream("storedProcedures/createStudent.js"); String spContent = IOUtils.toString(is, StandardCharsets.UTF_8); CosmosStoredProcedureProperties definition = new CosmosStoredProcedureProperties(spId, spContent); // 获取存储过程引用并检查是否存在 CosmosStoredProcedure spReference = container.getScripts().getStoredProcedure(spId); if (!spReference.exists()) { // 不存在则创建 return container.getScripts().createStoredProcedure(definition); } else { // 已存在则返回读取到的存储过程响应 // 若需要更新存储过程内容,可替换为 spReference.replace(definition) return spReference.read(); } } private InputStream getFileFromResourceAsStream(String fileName) { ClassLoader classLoader = getClass().getClassLoader(); InputStream inputStream = classLoader.getResourceAsStream(fileName); if (inputStream == null) { throw new IllegalArgumentException("file not found! " + fileName); } return inputStream; } }
关键说明
- 使用
CosmosStoredProcedure.exists()方法判断存储过程是否存在,该方法会处理404(资源不存在)的情况,返回false - 若需要在存储过程内容更新时自动同步,可以将
return spReference.read()替换为return spReference.replace(definition),这样每次重启会用最新的JS文件内容覆盖已有存储过程 - 确保存储过程的ID(示例中为
spCreateToDoItems)在容器内唯一,避免和其他存储过程冲突
内容的提问来源于stack exchange,提问作者Loren
相关产品推荐
相关产品推荐

