Java 定制用于多个数据源的Spring数据存储库bean名称
我有一个利用Spring数据(本例中为MongoDB)与具有相同模式的多个数据库交互的项目。这意味着每个数据库都使用相同的实体和存储库类。例如:Java 定制用于多个数据源的Spring数据存储库bean名称,java,spring,mongodb,spring-data,spring-data-mongodb,Java,Spring,Mongodb,Spring Data,Spring Data Mongodb,我有一个利用Spring数据(本例中为MongoDB)与具有相同模式的多个数据库交互的项目。这意味着每个数据库都使用相同的实体和存储库类。例如: public class Thing { private String id; private String name; private String type; // etc... } public interface ThingRepository extends PagingAndSortingReposit
public class Thing {
private String id;
private String name;
private String type;
// etc...
}
public interface ThingRepository extends PagingAndSortingRepository<Thing, String> {
List<Thing> findByName(String name);
}
@Configuration
@EnableMongoRepositories(basePackageClasses = { ThingRepository.class })
public MongoConfig extends AbstractMongoConfiguration {
// Standard mongo config
}
我可以使用不同的MongoTemplate
实例创建同一存储库的多个实例,但我不知道引用和注入它们的正确方法。我希望能够将各个存储库实例注入到不同的控制器中,如下所示:
@Controller
@RequestMapping("/things/one/")
public class ThingOneController {
@Resource private ThingRepository thingRepositoryOne;
...
}
@Controller
@RequestMapping("/things/two/")
public class ThingTwoController {
@Resource private ThingRepository thingRepositoryTwo;
...
}
这样的配置可能吗?我是否可以控制实例化接口的bean名称,以便使用@Resource
或@Autowired
引用它们
附加问题:这也可以通过自定义存储库工厂来实现吗?对于一般的
@repository
您可以添加(value=“someDao”)
来命名创建的Bean,如果MongoRepository
扩展了Repository
,这应该可以工作。使用@NoRepositoryBean
创建您的存储库接口,我们将自己连接它:
@NoRepositoryBean
public interface ModelMongoRepository extends MongoRepository<Model, String> {
}
现在,您有两个具有不同的@Qualifier
名称的bean,每个bean都为不同的数据库配置,并且使用相同的模型
您可以使用@Qualifier
注入它们:
@Autowired
@Qualifier("one")
private ModelMongoRepository mongoRepositoryOne;
@Autowired
@Qualifier("two")
private ModelMongoRepository mongoRepositoryTwo;
为了简单起见,我已经在configuration类中硬编码了这些值,但是您可以从application.properties/yml中的属性注入它们
编辑以回答评论:
如果您想创建一个自定义实现而不失去spring数据接口存储库的好处,这里有一些修改。规格说明如下:
通常有必要为一些应用程序提供自定义实现
存储库方法。Spring数据存储库允许您轻松地
提供自定义存储库代码并将其与通用CRUD集成
抽象和查询方法功能。丰富知识库
使用自定义功能,首先定义接口和
自定义功能的实现。使用存储库
为扩展自定义接口而提供的接口。最
要找到的类的重要位是
与核心存储库界面(见下文)相比,其上的名称
创建一个新接口,它在技术上与spring数据无关,好的旧接口:
public interface CustomMethodsRepository {
public void getById(Model model){
}
@NoRepositoryBean
public interface ModelMongoRepository extends MongoRepository<Model, String>, CustomMethodsRepository {
}
public class ModelMongoRepositoryImpl implements CustomModelMongoRepository {
private MongoOperations mongoOperations;
public ModelMongoRepositoryImpl(MongoOperations mongoOperations) {
this.mongoOperations = mongoOperations;
}
public void getById(Model model){
System.out.println("test");
}
}
让您的存储库接口扩展此新接口:
public interface CustomMethodsRepository {
public void getById(Model model){
}
@NoRepositoryBean
public interface ModelMongoRepository extends MongoRepository<Model, String>, CustomMethodsRepository {
}
public class ModelMongoRepositoryImpl implements CustomModelMongoRepository {
private MongoOperations mongoOperations;
public ModelMongoRepositoryImpl(MongoOperations mongoOperations) {
this.mongoOperations = mongoOperations;
}
public void getById(Model model){
System.out.println("test");
}
}
将Java配置更改为添加myFactory.setCustomImplementation(new ModelMongoRepositoryImpl())代码>:
@Bean
@Qualifier("one")
public ModelMongoRepository modelMongoRepositoryOne() throws DataAccessException, Exception {
MongoRepositoryFactoryBean<ModelMongoRepository, Model, String> myFactory = new MongoRepositoryFactoryBean<ModelMongoRepository, Model, String>();
MongoOperations mongoOperations = createMongoOperations("hostname1", 21979, "dbName1", "usdername1", "password1");
myFactory.setCustomImplementation(new ModelMongoRepositoryImpl(mongoOperations));
myFactory.setRepositoryInterface(ModelMongoRepository.class);
myFactory.setMongoOperations(mongoOperations);
myFactory.afterPropertiesSet();
return myFactory.getObject();
}
@Bean
@限定词(“一”)
public ModelMongoRepository modelMongoRepositoryOne()引发DataAccessException,异常{
MongoRepositoryFactoryBean myFactory=新的MongoRepositoryFactoryBean();
MongoOperations MongoOperations=createMongoOperations(“hostname1”,21979,“dbName1”,“usdername1”,“password1”);
myFactory.setCustomImplementation(新模型MongoRepositoryImpl(mongoOperations));
setRepositoryInterface(ModelMongoRepository.class);
myFactory.setMongoOperations(mongoOperations);
myFactory.AfterPropertieSet();
返回myFactory.getObject();
}
如果您没有通过Java配置手动连接存储库,则必须将此实现命名为ModelMongoRepositoryImpl
,以匹配接口ModelMongoRepository+“Impl”
。它将由spring自动处理。这对我没有帮助,因为每个存储库都有多个实例正在创建。使用@Repository(name=“myRepository”)
将产生两个同名的bean。我想确保由存储库工厂bean创建的对象以不同的编程方式命名。您可以这样做@Autowire@Qualifier(“mongoTemplateOne”)。我不是在尝试注入单个MongoTemplate
对象,我是在尝试注入它们用于创建的存储库。在我提供的示例中,您将如何注入使用任一数据源创建的ThingRepository
?如何从wired mongoTemplate获取存储库?您可能需要使用工厂手动实例化存储库实现,在这一点上,你可以使用普通的@Bean
技术来命名它们。@chrylis:你能提供一个例子作为答案吗?我不确定创建工厂bean和存储库实例的最佳方法是什么。我只讨论了手动创建,在这一点上我不能给你很好的建议。Oliver Gierke可能会在几个小时后出现。如果我添加了自定义方法,例如使用ThingRepository.findByName()
,该怎么办?或者如果我在ThingRepositoryImpl
类中有自定义实现的方法?我是否需要在Spring将要注入MongoTemplate
的具体类中手动实现它们?如果是这样的话,那么使用Spring Data的repository factory还有什么意义呢?我明白你的意思,我将更新代码以使用Interface+MongoRepositoryFactoryBeanThanks,这看起来会起作用,但是现在我被如何将MongoTemplates
注入ThingRepositoryImpl
中挂起了。我应该自定义实现findByName(…)
还是其他方法。想法?在这里,我相信这是你一直在寻找的最终解决方案!浏览最后一部分(“编辑以回答评论”)。你可以用最少的代码实现你的目标。这就成功了!在我的例子中,我还必须添加行myFactory.setRepositoryBaseClass(MyBaseRepository.class)
因为我有一个扩展了SimpleMongoRepository
的基本存储库类,但是在其他方面,配置是按照描述的那样工作的。这是一个巨大的帮助,谢谢!