如何在运行时注入和更改数据库/数据源?



首先,我使用JpaRepository为我的实体Foo类创建了标准存储库,以将其存储在数据库中。

public interface FooRepository extends JpaRepository<Foo, Long> {
}

此外,作为我的第二个数据访问对象,我想使用我自己的实现这个简单的 CRUD 操作接口,它将数据存储在文件中。

public interface FooDao {
Collection<Foo> getAll();
Foo getById(Long id);
void removeById(Long id);
void update(Foo foo);
void insert(Foo foo);
}

另外,当我像这样手动声明两个变量时,它可以正常工作

@Autowired
private FooRepository fooRepository;
@Autowired
private FooDao fooDao;

从服务中,我使用某种switch语句来识别当前用户选择的数据源,使用帮助变量:

private String datasource = "db";    // or "file"

但是这个解决方案需要使用if语句来确定我需要使用哪个数据访问对象,哪些重复代码,当然也不优雅。

public Foo getOne(Long id){
Foo result = null;
if(datasource.equals("db"))
result = fooRepository.findOne(id); 
else if(datasource().equals("file"))
result = fooDao.getById(id);            
return result;
}

如何在运行时在这些不同和不兼容的接口之间动态更改?如何使它们兼容以互换使用它们,如何正确编写某种包装器?

你可以让你的FooDao实现实现FooRepository接口,而不是你自己的接口。通过这种方式,您只需为接口提供 2 种不同的实现,并且可以在服务中以相同的方式处理它们。它们只是两个不同的春豆:

@Autowired  私有 FooRepository fooRepository;  @Autowired  私人 FooRepository fooDao;

您的实现将如下所示:

@Component public class FooDaoImpl implements FooRepository { 你自己对FooRepository声明的方法的实现 }

在您的 using 类中,您可以使用访问方法来获取如下所示的接口之一:

private FooRepository getFooDataAccess() { 返回 "db".equals(数据源) ?foo存储库:fooDao; }

若要避免条件语句,need使用公用接口。
问题在于,FooDaoJpaRepository都不是成为通用接口的好候选者。

JpaRepository子类在生成的实现运行时受益,因此您无法将生成的实现备份到FooDao接口。

FooDao子类实现JpaRepository也没有意义,因为它会强制FooDao实现与JpaRepository耦合并实现其中的所有方法(几十个),而它可能不能。
您可以为不支持的方法抛出UnsupportedOperationException,但它会使您的代码更加脆弱,因为只有在运行时才会检测到误用。

所以我认为在这些特定条件下,你包装两个对象的实际方式是一种有效的方法。

最新更新