spring Sping Boot 和mongodb,域类问题与findAll()和findById()有关

ebdffaop  于 2022-12-10  发布在  Spring
关注(0)|答案(1)|浏览(163)

我正在使用底层mongodb数据库实现一个spring Boot 服务,用于数据存储。
在这个服务中,我不得不使用一些来自另一个库的域类,我不能修改它们。不幸的是,这些类的示例变量被标记为final。例如,下面是Discount域类:

@Value
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@SuperBuilder(toBuilder = true)
@JsonDeserialize(builder = Discount.DiscountBuilderImpl.class)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class Discount extends AbstractEntityBase {

    @NonNull
    UUID id;

    @NonNull
    String no;

    @JsonProperty("iNo")
    Integer iNo;

    @NonNull
    LocalizedTexts designation;

    LocalizedTexts printText;
    
    boolean isAutomatic;

    LocalDate validFromDate;

    LocalDate validToDate;

    LocalTime validFromTime;

    LocalTime validToTime;

    String checkScriptParameters;

    ReferenceScript checkScript;

    @NonNull
    ReferenceScript calculationScript;

    public static DiscountBuilder<?, ?> builder(UUID id,
                                            String no,
                                            LocalizedTexts designation,
                                            ReferenceScript calculationScript,
                                            boolean isAutomatic) {
        return new DiscountBuilderImpl()
            .id(id)
            .no(no)
            .designation(designation)
            .calculationScript(calculationScript)
            .isAutomatic(isAutomatic);
    }

     /**
     * Overwritten getters for optional properties
     */
    ...

    @JsonPOJOBuilder(withPrefix = "")
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static final class DiscountBuilderImpl
        extends DiscountBuilder<Discount, DiscountBuilderImpl> {

    }
}

在我的测试类中,我正在测试保存和find(findAll,findById)操作。Save操作运行正常,但findAll和findById方法有问题。下面是这样一个测试类:

@RunWith(SpringRunner.class)
@DataMongoTest
public class TestDiscountRepository {
    @Autowired
    DiscountRepository discountRepository;

    @Before
    public void init(){
    }

    @After
    public void resetMongoDb() {
        //discountRepository.deleteAll();
    }

    @Test
    public void save_success() {

        UUID id = UUID.randomUUID();
        ...
        
        Discount discount = Discount.builder(id, no, designation, calculationScript, true)
                .iNo(iNo)
                .printText(printText)
                .isAutomatic(isAutomatic)
                .validFromDate(validFromDate)
                .validToDate(validToDate)
                .validFromTime(validFromTime)
                .validToTime(validToTime)
                .checkScriptParameters(checkScriptParameters)
                .checkScript(checkScript)
                .build();

        Discount savedDiscount = discountRepository.save(discount);

        assertThat(savedDiscount).isNotNull();
        assertThat(savedDiscount.getId()).isNotNull();
    }

    @Test
    public void save_bulk_success() {

        UUID id1 = UUID.randomUUID();
        ...

        UUID id2 = UUID.randomUUID();
        ...

        UUID id3 = UUID.randomUUID();
        ...

        List<Discount> discounts = Arrays.asList(
                Discount.builder(id1, no1, designation1, calculationScript1, true)
                        ...
                        .build(),
                Discount.builder(id2, no2, designation2, calculationScript2, true)
                        ...
                        .build(),
                Discount.builder(id3, no3, designation3, calculationScript3, true)
                        ...
                        .build()
        );

        List<Discount> allDiscounts = discountRepository.saveAll(discounts);

        AtomicInteger validIdFound = new AtomicInteger();
        allDiscounts.forEach(discount -> {
            if(discount.getId() != null) {
                validIdFound.getAndIncrement();
            }
        });

        assertThat(validIdFound.intValue()).isEqualTo(3);
    }

    @Test
    public void find_all_success() {
        List<Discount> discounts = discountRepository.findAll();
        Assert.assertNotNull(discounts);
    }

    @Test
    public void find_by_id_success() {
        UUID id = UUID.randomUUID();
        String no = "900";
        ...

        Discount discount = Discount.builder(id, no, designation, calculationScript, true)
                        ...
                        .build();

        Discount savedDiscount = discountRepository.save(discount);
        Optional<Discount> result = discountRepository.findById(savedDiscount.getId());

        Assert.assertNotNull(result.get());
    }
}

下面是我尝试运行/测试findAll()和findById()时遇到的异常:

java.lang.IllegalStateException: Cannot set property id because no setter, no wither and it's not part of the persistence constructor private net.mspos.possible.svc_pos_controller_data.entity.Discount()!

at org.springframework.data.mapping.model.InstantiationAwarePropertyAccessor.setProperty(InstantiationAwarePropertyAccessor.java:118)
at org.springframework.data.mapping.model.ConvertingPropertyAccessor.setProperty(ConvertingPropertyAccessor.java:64)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readAndPopulateIdentifier(MappingMongoConverter.java:450)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.populateProperties(MappingMongoConverter.java:418)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:394)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readDocument(MappingMongoConverter.java:356)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:292)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:288)
at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:107)
at org.springframework.data.mongodb.core.MongoTemplate$ReadDocumentCallback.doWith(MongoTemplate.java:3207)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindOneInternal(MongoTemplate.java:2822)
at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:2529)
at org.springframework.data.mongodb.core.MongoTemplate.doFindOne(MongoTemplate.java:2499)
at org.springframework.data.mongodb.core.MongoTemplate.findById(MongoTemplate.java:888)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.findById(SimpleMongoRepository.java:132)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:529)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:639)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:163)
at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
at jdk.proxy2/jdk.proxy2.$Proxy93.findById(Unknown Source)
at net.mspos.possible.svc_pos_controller_data.repository.TestDiscountRepository.find_by_id_success(TestDiscountRepository.java:209)

下面也是导入数据库的文档的外观:

关于如何克服这个问题有什么想法吗?不幸的是,改变域类不是一个选择。

lb3vh1jj

lb3vh1jj1#

最后,在我的例子中,最简单和更方便的解决方案是避免使用存储库来Map域类,并提供基本的CRUD操作。
相反,我使用MongoCollection接口和ObjectMapper将对象序列化/反序列化到mongodb文档中,用于所有的CRUD操作。例如,一个域类的相关服务可以如下所示:

@Service
@EnableConfigurationProperties(MongoProperties.class)
public class DiscountMongoService implements BasicMongoService {
    private MongoProperties mongoProperties;
    private CustomMongoConfig customMongoConfig;
    private BusinessEntityMapper mapper;

    private MongoCollection<Document> discountCollection;

    @Autowired
    public DiscountMongoService(MongoProperties mongoProperties, CustomMongoConfig customMongoConfig, BusinessEntityMapper mapper) {
        this.mongoProperties = mongoProperties;
        this.customMongoConfig = customMongoConfig;
        this.mapper = mapper;
        discountCollection =
            this.customMongoConfig.mongoClient().getDatabase(this.mongoProperties.getDatabase()).getCollection(Discount.class.getSimpleName());
}

    // Insert
    public boolean insertOne(Discount discount) throws JsonProcessingException {
        Document discountDoc = transformEntityIntoDocumentWithMongodbId(discount);
        InsertOneResult result = discountCollection.insertOne(discountDoc);
        System.out.println(result);
        return result.wasAcknowledged();
    }
    ....

    // Find
    public List<Discount> findAll() {
        List<Discount> discounts = new ArrayList<>();
        discountCollection.find().forEach(dd -> {
            Discount discount;
            try {
                discount = (Discount) mapper.getBusinessEntityFromJSON(dd.toJson(),Discount.class);
                discounts.add(discount);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        });
        return discounts;
    }

相关问题