项目配置为使用多个 MongoTemplate s
Mongo Ref作为
传递@EnableMongoRepositories(basePackages={"com.mypackage.one"}, mongoTemplateRef="mongoTemplateOne")
包com.mypackage.one
和
@EnableMongoRepositories(basePackages={"com.mypackage.two"}, mongoTemplateRef="mongoTemplateTwo")
包com.mypackage.two
对于标准存储库,它工作正常。但对于我需要自定义行为的场景,我定义了 myRepoCustomImpl 以及我的自定义行为需求。
问题:我需要访问类似标准存储库的 MongoTemplate 。
e.g。
如果MyRepo
正在将MyRepoCustom
接口扩展为
@Repository
interface MyRepo extends MongoRepository<MyEntity, String>, MyRepoCustom{}
MyRepoCustomImpl
@Service
public class MyRepoCustomImpl implements MyRepoCustom{
@Autowired
@Qualifier("mongoTemplateOne")
MongoTemplate mongoTmpl;
@Override
MyEntity myCustomNeedFunc(String arg){
// MyImplemenation goes here
}
}
如果 MyRepo 位于包com.mypackage.one
中,myRepo将使用mongoTemplateOne
,因此应该有一些方法让MyRepoCustomImpl知道它也应该使用< strong> mongoTemplateOne ,每当我在mongoTemplateRef
MyRepo
进行更改时,就像
@EnableMongoRepositories(basePackages={"com.mypackage.one"}, mongoTemplateRef="mongoTemplateThree")
现在我需要在MyRepoCustomImpl
中对@Qualifier进行更改!
有很多带有自定义行为的回购,因此它变得繁琐乏味。
问题:相反,没有任何方法可以根据它扩展到的回购自动注入或解决使用的MongoTemplate?
答案 0 :(得分:1)
MongoTemplate
接口未公开 MongoRepository
。他们可能会公开MongoTemplate
@Bean
的名称,这可能会为您的问题提供解决方案。但是,鉴于他们不这样做,我将在下面提供一个可能符合您需求的示例。
首先关闭mongoTemplateRef
是指要使用的@Bean
的名称,它不会指定MongoTemplate
的名称。
您需要提供每个MongoTemplate
@Bean
,然后在@EnableMongoRepositories
注释中引用它。
由于您使用的是spring-boot,因此您可以利用MongoDataAutoConfiguration
类。请看一下这里的作用https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/mongo/MongoDataAutoConfiguration.java。
最简单的例子就是这个。
package: com.xyz.repo(此实现依赖于MongoDataAutoConfiguration
提供的配置)
@Configuration
@EnableMongoRepositories(basePackages={"com.xyz.repo"}) //mongoTemplateRef defaults to mongoTemplate
public class XyzRepoConfiguration {
}
public abstract class BaseRepo {
@Autowired
MongoTemplate mongoTemplate;
}
@Service
public class MyRepoCustomImpl extends BaseRepo implements MyRepoCustom {
@Override
MyEntity myCustomNeedFunc(String arg){
// access to this.mongoTemplate is present
}
}
包: com.abc.repo
@Configuration
@EnableMongoRepositories(basePackages={"com.abc.repo"}, mongoTemplateRef=AbcRepConfiguration.TEMPLATE_NAME)
public class AbcRepoConfiguration {
public static final String TEMPLATE_NAME = "mongoTemplateTwo";
@Bean(name="mongoPropertiesTwo")
@ConfigurationProperties(prefix="spring.data.mongodb2")
public MongoProperties mongoProperties() {
return new MongoProperties();
}
@Bean(name="mongoDbFactoryTwo")
public SimpleMongoDbFactory mongoDbFactory(MongoClient mongo, @Qualifier("mongoPropertiesTwo") MongoProperties mongoProperties) throws Exception {
String database = this.mongoProperties.getMongoClientDatabase();
return new SimpleMongoDbFactory(mongo, database);
}
@Bean(name=AbcRepoConfiguration.TEMPLATE_NAME)
public MongoTemplate mongoTemplate(@Qualifier("mongoDbFactoryTwo") MongoDbFactory mongoDbFactory, MongoConverter converter) throws UnknownHostException {
return new MongoTemplate(mongoDbFactory, converter);
}
}
public abstract class BaseRepo {
@Autowired
@Qualifier(AbcRepoConfiguration.TEMPLATE_NAME)
MongoTemplate mongoTemplate;
}
@Service
public class MyRepoCustomImpl extends BaseRepo implements MyRepoCustom {
@Override
MyEntity myCustomNeedFunc(String arg){
// access to this.mongoTemplate is present
}
}
com.xyz.repo 将依赖spring.data.mongodb
中的application.properties
个属性
com.abc.repo 将依赖于spring.data.mongodb2
application.properties
个属性
之前我没有使用过AbcRepoConfiguration.TEMPLATE_NAME方法,但它是在我的IDE中编译的。
如果您需要任何澄清,请告诉我。
答案 1 :(得分:1)
MongoTemplate
未在您的存储库类中注入,但在spring-data-mongodb
中更深入,因此您无法从存储库中获取它。看看你会学到很多东西的代码。
所以不能根据repo扩展注入一个bean,除非你禁用spring-boot自动配置和组件发现并自己配置它,但它会比只更改{{1 }} 名称。您的IDE调用可以轻松地帮助您,您可能会后悔禁用自动配置。
对于失望感到抱歉。
答案 2 :(得分:1)
您可以使用以下示例。
1)
package com.johnathanmarksmith.mongodb.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* Date: 6/28/13 / 10:40 AM
* Author: Johnathan Mark Smith
* Email: john@johnathanmarksmith.com
* <p/>
* Comments:
* This main really does not have to be here but I just wanted to add something for the demo..
*
*/
public class MongoDBApp {
static final Logger logger = LoggerFactory.getLogger(MongoDBApp.class);
public static void main(String[] args) {
logger.info("Fongo Demo application");
ApplicationContext context = new AnnotationConfigApplicationContext(MongoConfiguration.class);
logger.info("Fongo Demo application");
}
}
2)
package com.johnathanmarksmith.mongodb.example;
import com.mongodb.Mongo;
import com.mongodb.ServerAddress;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import java.util.ArrayList;
/**
* Date: 5/24/13 / 8:05 AM
* Author: Johnathan Mark Smith
* Email: john@johnathanmarksmith.com
* <p/>
* Comments:
* <p/>
* This is a example on how to setup a database with Spring's Java Configuration (JavaConfig) style.
* <p/>
* As you can see from the code below this is easy and a lot better then using the old style of XML files.
* <p/>
* T
*/
@Configuration
@EnableMongoRepositories
@ComponentScan(basePackageClasses = {MongoDBApp.class})
@PropertySource("classpath:application.properties")
public class MongoConfiguration extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "demo";
}
@Override
public Mongo mongo() throws Exception {
/**
*
* this is for a single db
*/
// return new Mongo();
/**
*
* This is for a relset of db's
*/
return new Mongo(new ArrayList<ServerAddress>() {{ add(new ServerAddress("127.0.0.1", 27017)); add(new ServerAddress("127.0.0.1", 27027)); add(new ServerAddress("127.0.0.1", 27037)); }});
}
@Override
protected String getMappingBasePackage() {
return "com.johnathanmarksmith.mongodb.example.domain";
}
}
3)
package com.johnathanmarksmith.mongodb.example.repository;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import com.johnathanmarksmith.mongodb.example.domain.Person;
/**
* Date: 6/26/13 / 1:22 PM
* Author: Johnathan Mark Smith
* Email: john@johnathanmarksmith.com
* <p/>
* Comments:
* <p/>
* This is my Person Repository
*/
@Repository
public class PersonRepository {
static final Logger logger = LoggerFactory.getLogger(PersonRepository.class);
@Autowired
MongoTemplate mongoTemplate;
public long countUnderAge() {
List<Person> results = null;
Query query = new Query();
Criteria criteria = new Criteria();
criteria = criteria.and("age").lte(21);
query.addCriteria(criteria);
//results = mongoTemplate.find(query, Person.class);
long count = this.mongoTemplate.count(query, Person.class);
logger.info("Total number of under age in database: {}", count);
return count;
}
/**
* This will count how many Person Objects I have
*/
public long countAllPersons() {
// findAll().size() approach is very inefficient, since it returns the whole documents
// List<Person> results = mongoTemplate.findAll(Person.class);
long total = this.mongoTemplate.count(null, Person.class);
logger.info("Total number in database: {}", total);
return total;
}
/**
* This will install a new Person object with my
* name and random age
*/
public void insertPersonWithNameJohnathan(double age) {
Person p = new Person("Johnathan", (int) age);
mongoTemplate.insert(p);
}
/**
* this will create a {@link Person} collection if the collection does not already exists
*/
public void createPersonCollection() {
if (!mongoTemplate.collectionExists(Person.class)) {
mongoTemplate.createCollection(Person.class);
}
}
/**
* this will drop the {@link Person} collection if the collection does already exists
*/
public void dropPersonCollection() {
if (mongoTemplate.collectionExists(Person.class)) {
mongoTemplate.dropCollection(Person.class);
}
}
}
4)
package com.johnathanmarksmith.mongodb.example.domain;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* Date: 6/26/13 / 1:21 PM
* Author: Johnathan Mark Smith
* Email: john@johnathanmarksmith.com
* <p/>
* Comments:
* <p/>
* This is a Person object that I am going to be using for my demo
*/
@Document
public class Person {
@Id
private String personId;
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getPersonId() {
return personId;
}
public void setPersonId(final String personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(final int age) {
this.age = age;
}
@Override
public String toString() {
return "Person [id=" + personId + ", name=" + name
+ ", age=" + age + "]";
}
}
答案 3 :(得分:-1)
您可以直接在服务类中注入MongoTemplate和MongoOperations。
尝试自动连接它们然后你应该很好。
更新
如果没有使用适当的限定符进行自动装配(因为您有两个存储库),这是不可能的。作为Custom类,所有这些都与存储库不同。如果你只有一个存储库,那么mongotemplate的autowire就足够了,否则你必须在impl中提供限定符,因为创建了两个MongoTempalte bean。