我正在使用底层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)
下面也是导入数据库的文档的外观:
关于如何克服这个问题有什么想法吗?不幸的是,改变域类不是一个选择。
1条答案
按热度按时间lb3vh1jj1#
最后,在我的例子中,最简单和更方便的解决方案是避免使用存储库来Map域类,并提供基本的CRUD操作。
相反,我使用MongoCollection接口和ObjectMapper将对象序列化/反序列化到mongodb文档中,用于所有的CRUD操作。例如,一个域类的相关服务可以如下所示: