保存mongo结果时出现重复键错误

mwngjboj  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(383)

尝试使用React流查询和更新mongodb的某些记录时,我看到以下错误:

org.springframework.dao.DuplicateKeyException: E11000 duplicate key error collection: testtrans.submission index: _id_ dup key: { _id: ObjectId('600b10b2fbac4f4483af3e67') }; nested exception is com.mongodb.MongoWriteException

我不确定我做错了什么;如何在单个事务中使用reactive mongo查询结果并将结果保存到数据库中?
我的服务级别:

package com.example.reactivemongotransaction.service;

import com.example.reactivemongotransaction.dto.Submission;
import com.example.reactivemongotransaction.repository.SubmissionRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Slf4j
@Service
public class SubmissionService {

    @Autowired
    private SubmissionRepository submissionRepository;

    public Mono<Submission> saveSubmission(Submission submission) {
        log.debug("saving {}", submission);
        return submissionRepository.save(submission);
    }

    @Transactional
    public Flux<Submission> lockSubmissions() {
        log.debug("setting all locked");
        Flux<Submission> submissionFlux = submissionRepository.findAllByLockedFalse();
        return submissionFlux
                .map(submission -> submission.setLocked(true))
                .flatMap(submission -> submissionRepository.save(submission));
    }

}

我的配置:

@Configuration
@EnableMongoAuditing
@EnableTransactionManagement
public class MongoConfiguration { 

    @Bean
    public ReactiveTransactionManager transactionManager(ReactiveMongoDatabaseFactory dbFactory) {
        return new ReactiveMongoTransactionManager(dbFactory);
    }

}

控制器:

@RestController
@RequestMapping("/submissions")
public class SubmissionController {

    @Autowired
    private SubmissionService submissionService;

    @PostMapping
    public Mono<Submission> saveSubmission(final @RequestBody Submission submission) {
        return submissionService.saveSubmission(submission);
    }

    @GetMapping("/lockall")
    public Flux<Submission> lockAll() {
        return submissionService.lockSubmissions();
    }
}

型号:

@ToString
@Getter
@Setter
@Accessors(chain = true)
@Document(collection = "submission")
@TypeAlias("payload")
public class Submission implements Persistable<String> {

    @Id
    private String id;

    @Field("role_name")
    @Indexed(unique = true)
    private String role;

    @CreatedDate
    private ZonedDateTime created;

    @LastModifiedDate
    private ZonedDateTime updated;

    private Boolean deleted;

    private Boolean enabled;

    private boolean locked;

    @Override
    @JsonIgnore
    public boolean isNew() {
        if(getCreated() == null)
            return true;
        else
            return false;
    }
}

存储库:

public interface SubmissionRepository extends ReactiveMongoRepository<Submission, String> {

    Flux<Submission> findAllByLockedFalse();
}

主要类别:

@EnableReactiveMongoRepositories
@SpringBootApplication
public class ReactivemongotransactionApplication {

    public static void main(String[] args) {
        SpringApplication.run(ReactivemongotransactionApplication.class, args);
    }

}

应用程序.yml:

spring:
  data:
    mongodb:
      uri: 'mongodb://localhost:27017/testtrans'

server:
  port: 8280

Mavenpom:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>reactivemongotransaction</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>reactivemongotransaction</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <lombok.version>1.18.6</lombok.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

我的要求是 GET http://localhost:8280/submissions/lockall 返回500。日志显示错误,例如:

com.mongodb.MongoWriteException: E11000 duplicate key error collection: testtrans.submission index: _id_ dup key: { _id: ObjectId('600b10b2fbac4f4483af3e67') }
    at com.mongodb.internal.async.client.AsyncMongoCollectionImpl.lambda$executeSingleWriteRequest$9(AsyncMongoCollectionImpl.java:1075) ~[mongodb-driver-core-4.1.1.jar:na]
ufj5ltwl

ufj5ltwl1#

这个问题与 @CreatedDate 未设置(请参阅SpringBoot2.4.3中的@enablemongoauditing和@createddate auditing not working)。
通过还原解决 spring-boot-starter-parent 至2.3.5.版本。

相关问题