gpt4 book ai didi

java - 自定义 Spring 数据存储库 bean 名称以用于多个数据源

转载 作者:IT老高 更新时间:2023-10-28 13:49:17 25 4
gpt4 key购买 nike

我有一个项目,它利用 Spring Data(在本例中为 MongoDB)与具有相同架构的多个数据库进行交互。这意味着每个数据库都使用相同的实体和存储库类。所以,例如:

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
}

如果我要连接到单个数据库,这可以正常工作,但是当我想同时连接到多个数据库时,事情会变得更加复杂:

@Configuration
@EnableMongoRepositories(basePackageClasses = { ThingRepository.class },
mongoTemplateRef = "mongoTemplateOne")
public MongoConfigOne extends AbstractMongoConfiguration {

@Override
@Bean(name = "mongoTemplateOne")
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(this.mongo(), "db_one");
}

// Remaining standard mongo config

}

@Configuration
@EnableMongoRepositories(basePackageClasses = { ThingRepository.class },
mongoTemplateRef = "mongoTemplateTwo")
public MongoConfigTwo extends AbstractMongoConfiguration {

@Override
@Bean(name = "mongoTemplateTwo")
public MongoTemplate mongoTemplate() throws Exception {
return new MongoTemplate(this.mongo(), "db_two");
}

// Remaining standard mongo config

}

我可以使用不同的 MongoTemplate 实例创建同一个存储库的多个实例,但我不知道引用和注入(inject)它们的正确方法。我希望能够将各个存储库实例注入(inject)不同的 Controller ,如下所示:

@Controller
@RequestMapping("/things/one/")
public class ThingOneController {
@Resource private ThingRepository thingRepositoryOne;
...
}

@Controller
@RequestMapping("/things/two/")
public class ThingTwoController {
@Resource private ThingRepository thingRepositoryTwo;
...
}

这样的配置可能吗?我能否以某种方式控制实例化接口(interface)的 bean 名称,以便我可以使用 @Resource@Autowired 引用它们?

额外问题:这也可以通过自定义存储库工厂来完成吗?

最佳答案

使用 @NoRepositoryBean 创建您的存储库接口(interface),我们将自己连接它:

@NoRepositoryBean
public interface ModelMongoRepository extends MongoRepository<Model, String> {
}

然后,在 @Configuration 类中,使用 MongoRepositoryFactoryBean 实例化 2 个存储库 bean。两个存储库将返回相同的 Spring Data Repository 接口(interface),但我们将为它们分配不同的 MongoOperations(即:数据库详细信息):

@Configuration
@EnableMongoRepositories
public class MongoConfiguration {

@Bean
@Qualifier("one")
public ModelMongoRepository modelMongoRepositoryOne() throws DataAccessException, Exception {
MongoRepositoryFactoryBean<ModelMongoRepository, Model, String> myFactory = new MongoRepositoryFactoryBean<ModelMongoRepository, Model, String>();
myFactory.setRepositoryInterface(ModelMongoRepository.class);
myFactory.setMongoOperations(createMongoOperations("hostname1", 21979, "dbName1", "username1", "password1"));
myFactory.afterPropertiesSet();
return myFactory.getObject();
}

@Bean
@Qualifier("two")
public ModelMongoRepository modelMongoRepositoryTwo() throws DataAccessException, Exception {
MongoRepositoryFactoryBean<ModelMongoRepository, Model, String> myFactory = new MongoRepositoryFactoryBean<ModelMongoRepository, Model, String>();
myFactory.setRepositoryInterface(ModelMongoRepository.class);
myFactory.setMongoOperations(createMongoOperations("hostname2", 21990, "dbName2", "username2", "password2"));
myFactory.afterPropertiesSet();
return myFactory.getObject();
}

private MongoOperations createMongoOperations(String hostname, int port, String dbName, String user, String pwd) throws DataAccessException, Exception {
MongoCredential mongoCredentials = MongoCredential.createScramSha1Credential(user, dbName, pwd.toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress(hostname, port), Arrays.asList(mongoCredentials));
Mongo mongo = new SimpleMongoDbFactory(mongoClient, dbName).getDb().getMongo();
return new MongoTemplate(mongo, dbName);
}
//or this one if you have a connection string
private MongoOperations createMongoOperations(String dbConnection) throws DataAccessException, Exception {
MongoClientURI mongoClientURI = new MongoClientURI(dbConnection);
MongoClient mongoClient = new MongoClient(mongoClientURI);
Mongo mongo = new SimpleMongoDbFactory(mongoClient, mongoClientURI.getDatabase()).getDb().getMongo();
return new MongoTemplate(mongo, mongoClientURI.getDatabase());
}
}

您现在有 2 个具有不同 @Qualifier 名称的 bean,每个都为不同的数据库配置,并使用相同的模型。

您可以使用 @Qualifier 注入(inject)它们:

@Autowired
@Qualifier("one")
private ModelMongoRepository mongoRepositoryOne;

@Autowired
@Qualifier("two")
private ModelMongoRepository mongoRepositoryTwo;

为简单起见,我在配置类中硬编码了这些值,但您可以从 application.properties/yml 中的属性注入(inject)它们。

EDIT to answer comments:

如果你想创建一个自定义实现而不失去 Spring 数据接口(interface)存储库的好处,这里是修改。规范是这样说的:

Often it is necessary to provide a custom implementation for a few repository methods. Spring Data repositories easily allow you to provide custom repository code and integrate it with generic CRUD abstraction and query method functionality. To enrich a repository with custom functionality you first define an interface and an implementation for the custom functionality. Use the repository interface you provided to extend the custom interface. The most important bit for the class to be found is the Impl postfix of the name on it compared to the core repository interface (see below).

新建一个接口(interface),技术上和spring数据无关,好旧的接口(interface):

public interface CustomMethodsRepository {
public void getById(Model model){
}

让您的存储库接口(interface)扩展这个新接口(interface):

@NoRepositoryBean
public interface ModelMongoRepository extends MongoRepository<Model, String>, CustomMethodsRepository {
}

然后,创建您的实现类,它实现您的非 spring-data 接口(interface):

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();
}

如果您没有通过 Java 配置手动连接存储库,则必须将此实现命名为 ModelMongoRepositoryImpl 以匹配接口(interface) ModelMongoRepository +"Impl"。并且会被spring自动处理。

关于java - 自定义 Spring 数据存储库 bean 名称以用于多个数据源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38337453/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com