Java 复制MongoDB+spring数据MongoDB

Java 复制MongoDB+spring数据MongoDB,java,spring,mongodb,spring-data-mongodb,mongodb-replica-set,Java,Spring,Mongodb,Spring Data Mongodb,Mongodb Replica Set,有一个复制的mongodb mongodb-1-主、mongodb-2-次、mongodb-3-次。 该应用程序通过spring boot starter数据mongodb运行 服务: public class FooBarService { private FooBarRepository repository; public FooBar method1() { return repository.someQuery(); } public FooBar me

有一个复制的mongodb mongodb-1-主、mongodb-2-次、mongodb-3-次。 该应用程序通过spring boot starter数据mongodb运行

服务:

public class FooBarService {
  private FooBarRepository repository;

  public FooBar method1() {
    return repository.someQuery();
  }
  
  public FooBar method2() {
    return repository.someQuery();
  }
}
存储库:

public interface FooBarRepository extends MongoRepository<FooBar, String> {
  FooBar someQuery();
}
我的问题是,让method1读取mongo副本集中的主要参与者,method2读取mongo副本集中的次要参与者,这样做有多好

希望找到某种方法在服务级别(如@Transactional)管理此问题,但选择mongo副本集成员

您能就这方面的解决方案向我提供建议吗?

解决方案1:@Meta Annotation 如果要继续使用存储库接口,可以使用@Meta注释对查询方法定义进行注释,该注释允许您传递标志以指示从辅助mongodb成员读取

public interface FooBarRepository extends MongoRepository<FooBar, String> {

  @Query("{}")
  @Meta(flags = Meta.CursorOption.SECONDARY_READS)
  FooBar someQuery();
}

无论您选择哪种解决方案:请注意,从辅助成员读取数据可能会导致检索过时数据

是的,我也只知道这些解决方案,但它们看起来要么太混乱,像Meta,要么像MongoTemplate一样麻烦。也许您可以建议如何包装MongoTemplate,使其从服务级别工作?可能是AOP。类似@Transactional的东西我猜不支持,而且我不认为SpringDataMongoDB会支持这个用例。这也将是相当困难的实施它自己。在我看来,这完全属于存储库,不应该由服务层控制。也许你可以解释一下你的用例来获得一些上下文。在我的应用程序中,二次读取错误并不重要,但对于一些方法来说,它是重要的。存储库方法从这两种类型调用我,因此使用第二层进行调用是有问题的。可以使用MongoTemplate,但这会使应用程序逻辑复杂很多。我只想找到一种方法来管理这个过程,而不影响业务逻辑的主代码。甚至可能是一个解决方案的独立实现,但为了自己实现,您需要了解采用哪一方的方法。好的。所以,如果您真的想在任何应用层控制器上提出解决方案,服务。。。并且想要以@Transactional的方式来完成,您必须创建一个自定义注释,使用例如SpringAOP截取目标方法,并将有关读取首选项的信息存储在某个上下文/线程本地。创建一个自定义MongoTemplate,该MongoTemplate继承默认的spring MongoTemplate,重写executeQuery方法,并设置标志(如果在上下文中)。但如果不正确实施,所有这些都会产生副作用。我不同意这个解决方案
public void someQuery(boolean readFromSecondary) {
    var query = Query.query(Criteria.where("someKey").is("1"));

    if (readFromSecondary) {
        query.allowSecondaryReads();
    }

    return mongoTemplate.findOne(query, FooBar.class);
}