我正在 Spring MVC 中通过 mongodb java 驱动程序连接到 MongoDB 分片服务器。我正在使用以下版本:
我的 Mongo 选项在 contextConfigLocation 文件 mvc-dispatcher-servlet.xml 中设置
<mongo:mongo host="mongo.sample.com" port="30000">
<mongo:options auto-connect-retry="true"
slave-ok="true"/>
</mongo:mongo>
它工作得很好,但 come.MongoDB.ReadPreference 已弃用从属 ok。 我只是想知道是否有任何方法可以在 contextConfiLocation 文件中设置 Spring MVC 的 readPreference 。
声明以下 bean
<bean id="readPreferenceSecondary" class="com.mongodb.TaggableReadPreference.SecondaryReadPreference">
</bean>
和
你将其注入到你的 mongotemplate 中
<bean id="mongoTemplateProdDb" class="org.springframework.data.mongodb.core.MongoTemplate" >
<property name="readPreference" ref="readPreferenceSecondary"></property>
</bean>
ReadPreference
设置为 SECONDARY
,将@Trisha 的回复扩展为答案:“以编程方式在 MongoTemplate 中执行”。
MongoTemplate template = new MongoTemplate(...);
template.setReadPreference(com.mongodb.ReadPreference.SECONDARY);
如果您使用 spring-data-mongodb 并且需要基于查找查询使用多个读取首选项,您可以创建多个 Mongo 模板和/或存储库,例如
@EnableMongoRepositories(basePackages = {
"com.you.repo.package" }, mongoTemplateRef = "mongoTemplateOne")
@Configuration
public class MongoConfig {
@Bean(name="mongoTemplateOne")
public MongoTemplate getMongoTemplateOne() throws UnknownHostException {
MongoTemplate templateOne = new MongoTemplate(new SimpleMongoDbFactory(new MongoClientURI("YOUR_MONGO_URL")));
templateOne.setReadPreference(ReadPreference.secondaryPreferred());
//setting WriteConcern but not relevant for this thread
templateOne.setWriteConcernResolver(yourWriteConcernResolver());
return templateOne;
}
@Bean(name = "mongoTemplateTwo")
public MongoTemplate getMongoTemplateTwo() throws UnknownHostException {
MongoTemplate templateTwo = new MongoTemplate(new SimpleMongoDbFactory(new MongoClientURI("YOUR_MONGO_URL")));
templateTwo.setReadPreference(ReadPreference.secondaryPreferred());
return templateTwo;
}
private WriteConcernResolver yourWriteConcernResolver() {
return action -> {
if (action.getCollectionName()
.equals("your_collecton")
&& (action.getMongoActionOperation() == MongoActionOperation.SAVE
|| action.getMongoActionOperation() == MongoActionOperation.UPDATE)) {
return WriteConcern.MAJORITY;
}
return action.getDefaultWriteConcern();
};
}
如果您有多个辅助节点(副本集),您可以使用 tags 更具体地告诉 mongo 驱动程序您想要从哪个辅助节点读取。
在 mongo 端运行以下命令:
db.getMongo().setReadPref('secondaryPreferred',
[{"tagName":"TagVal1"},
{"tagName":"TagVal2"},
{}])
在代码中它看起来像这样:
MongoTemplate template = new MongoTemplate(...)
template.setReadPreference(ReadPreference.secondaryPreferred("your DBObject that reflect your mongo tag names");
希望有帮助。
这是使用 Mongo 存储库执行此操作的另一种方法
@Configuration
@EnableMongoRepositories
class ApplicationConfig extends AbstractMongoClientConfiguration {
@Autowired
private Environment env;
@Value("${spring.data.mongodb.uri}")
public String mongoUri;
@Override
protected String getDatabaseName() {
return env.getProperty("spring.data.mongodb.database");
}
@Override
protected void configureClientSettings(MongoClientSettings.Builder builder) {
builder.applyConnectionString(new ConnectionString(mongoUri)).readPreference(ReadPreference.secondary());
}
}
如果需要根据集合混合主次读取,可以在
ReadPreference
对象上设置 DBCollection
。这有助于避免复杂的多个 MongoTemplate
配置。相反,在应用程序生命周期中设置一次集合级别首选项,如下所示。 该特定集合的所有读取都将转到辅助集合,而对于其他集合,它将转到主要集合。
DBCollection dbCollection = mongoTemplate.getCollection(mongoTemplate.getCollectionName(collection));
dbCollection.setReadPreference(ReadPreference.secondaryPreferred());
如果你想了解不同的实现方案,请查看Spring data mongodb二次读取
从 spring-mongo-2.0.xsd 开始,
slave-ok
已被完全删除,但添加了对 ReadPreference
的 XML 配置的支持。以下是针对当前 XSD 翻译的原始问题的 XML:
<mongo:mongo-client host="mongo.sample.com" port="30000">
<mongo:client-options read-preference="SECONDARY_PREFERRED" />
</mongo:mongo-client>
或者您可以在存储库接口中使用注释在查询级别进行定义:
@Meta(flags = CursorOption.SECONDARY_READS)
Stream<MyClass> findBySomeField(String someField);
当使用 spring 从方法名称或注释(如 @Query 或 @Aggregation
)生成查询时,这非常有用如果您使用 SpringBoot 的“MongoRepository”接口,您只需将 @ReadPreference("secondaryPreferred") 添加到该方法即可。
public interface MyRepository extends MongoRepository<MyItem, String>
{
@ReadPreference("secondaryPreferred")
public Optional<MyItem> findById(String id);