[英]Passing MongoTemplate to Custom Repository implementation
Project配置為使用多個MongoTemplate
Mongo Ref被傳遞為
@EnableMongoRepositories(basePackages={"com.mypackage.one"}, mongoTemplateRef="mongoTemplateOne")
對於com.mypackage.one
包中的存儲庫
和
@EnableMongoRepositories(basePackages={"com.mypackage.two"}, mongoTemplateRef="mongoTemplateTwo")
對於com.mypackage.two
包中的存儲庫
對於標准存儲庫,它工作正常。 但對於我需要自定義行為的場景,我定義了myRepoCustomImpl以及我的自定義行為需求。
問題 :我需要訪問類似標准存儲庫的MongoTemplate 。
例如,如果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
包中, mongoTemplateOne
將被myRepo使用,所以應該有一些方法讓MyRepoCustomImpl知道它也應該使用mongoTemplateOne ,每當我在mongoTemplateRef
為MyRepo
進行更改時,就像
@EnableMongoRepositories(basePackages={"com.mypackage.one"}, mongoTemplateRef="mongoTemplateThree")
現在我需要在MyRepoCustomImpl
對@Qualifier進行更改! 自定義行為有很多回購,因此它變得繁瑣乏味。
問題:相反,沒有任何方法可以根據它擴展到的回購自動注入或解決使用的MongoTemplate?
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中編譯的。
如果您需要任何澄清,請告訴我。
MongoTemplate
不會在您的存儲庫類中注入,而是在spring-data-mongodb
更深入,因此您無法從存儲庫中獲取它。 看看你會學到很多東西的代碼。
因此,除非您禁用spring-boot自動配置和組件發現並自行配置它,否則不能根據repo擴展注入bean,但這比僅更改@Qualifier
名稱要長得多。 您的IDE調用可以輕松地幫助您,您可能會后悔禁用自動配置。
抱歉讓人失望。
您可以使用以下示例。
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 + "]";
}
}
您可以直接在服務類中注入MongoTemplate和MongoOperations。
嘗試自動連接它們然后你應該很好。
更新:
沒有使用適當的限定符自動裝配(因為你有兩個存儲庫),這是不可能的。 作為Custom類,所有這些都與存儲庫不同。 如果你只有一個存儲庫,那么mongotemplate的autowire就足夠了,否則你必須在impl中提供限定符,因為創建了兩個MongoTempalte bean。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.