提问人:zellcorp 提问时间:10/15/2023 最后编辑:zellcorp 更新时间:10/16/2023 访问量:62
实现 AbstractMongoEventListener 时事务不工作
Transactional not working while implementing AbstractMongoEventListener
问:
我尝试保存包含子文档列表的父文档。 在保存父项时,我检查是否需要根据注释保存嵌套的子项。 如果是,我将子文档保存在父文档之前,如果无法保存父文档,我想取消操作。
为了测试它,我在保存子文档后立即抛出异常,并检查文档是否已保存。
这是我使用的代码,这是我对 AbstractMongoEventListener.onBeforeConvert() 的实现:
@Component
public class CascadeSaveMongoListener extends AbstractMongoEventListener<Object> {
private final ReactiveMongoTemplate reactiveMongoTemplate;
public CascadeSaveMongoListener(ReactiveMongoTemplate reactiveMongoTemplate) {
this.reactiveMongoTemplate = reactiveMongoTemplate;
}
@Override
public void onBeforeConvert(BeforeConvertEvent<Object> event) {
ReflectionUtils.doWithFields(event.getSource().getClass(), new CascadeSaveCallback(event, reactiveMongoTemplate));
}
}
和这个回调:
public class CascadeSaveCallback implements ReflectionUtils.FieldCallback {
private MongoMappingEvent event;
private ReactiveMongoTemplate reactiveMongoTemplate;
CascadeSaveCallback(MongoMappingEvent event, ReactiveMongoTemplate reactiveMongoTemplate) {
this.event = event;
this.reactiveMongoTemplate = reactiveMongoTemplate;
}
@Override
public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
ReflectionUtils.makeAccessible(field);
if (field.isAnnotationPresent(DBRef.class) && field.isAnnotationPresent(CascadeSave.class)) {
final Object fieldValue = field.get(event.getSource());
if (Collection.class.isAssignableFrom(fieldValue.getClass())) {
Mono<Collection<Object>> mono = Mono.just((Collection<Object>) fieldValue);
reactiveMongoTemplate.insertAll(mono).then().subscribe();
throw new IllegalArgumentException("Not yet implemented");
} else {
reactiveMongoTemplate.insert(fieldValue);
}
}
}
}
为了给您提供更多信息, 我从官方映像中使用带有 docker 的 mongo,这里是我用来使用 replica 运行它并启用事务的命令:
$ docker run --name my-mongo -p 27017:27017 -d mongo --replSet rs0 && sleep 2 && docker exec my-mongo mongosh --eval "rs.initiate();"
这里是 SpringBootApplication 类、服务、Entity 和我的 mongoReactiveConfig 类:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableTransactionManagement
@EnableMongoRepositories
public class ApiApplication {
public static void main(String[] args) {
SpringApplication.run(ApiApplication.class, args);
}
}
@Service
public class ApiService {
private final ParentRepository parentRepository;
public ApiService(ParentRepository parentRepository) {
this.parentRepository = parentRepository;
}
@Transactional
public Mono<Parent> save(Parent parent) {
return parentRepository.save(parent);
}
}
@Document
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class Parent extends BaseEntity {
@JsonFormat(pattern = "dd-MM-yyyy HH:mm:ss")
private LocalDateTime startDate;
@DBRef
@CascadeSave
List<Child> children;
}
@Configuration
public class MongoReactiveConfig extends AbstractReactiveMongoConfiguration {
@Bean
ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory factory) {
return new ReactiveMongoTransactionManager(factory);
}
@Override
public MongoClient reactiveMongoClient() {
return MongoClients.create("mongodb://localhost:27017/api");
}
@Override
protected String getDatabaseName() {
return "api";
}
}
首先,我尝试不注入 ReactiveMongoTemplate。但交易没有成功。 然后我尝试了它,我得到了相同的结果。
当我运行代码时,我可以看到异常,但我仍然在mongoDB中看到Child文档,我希望它不在这里。
有人有想法吗? PS:英语不是我的母语,我为我犯的任何错误道歉。
编辑: 从我得到的日志来看,它似乎与调用 ApiService.save() 的线程与用于自定义侦听器的线程之间的绑定有关。 创建一个新事务,然后自定义侦听器抛出异常并开始回滚。 但是然后我可以看到插入指令的开始。
答: 暂无答案
评论