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

时间:2018-03-27 06:46:25

标签: java spring spring-boot

首先,我使用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;
}

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

2 个答案:

答案 0 :(得分:1)

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

   @Autowired
   private FooRepository fooRepository;

   @Autowired
   private FooRepository fooDao;

您的实施方式如下:

@Component
public class FooDaoImpl implements FooRepository {
  // your own implementations for the methods declared by FooRepository 
}

在你的使用类中,你可以使用一个访问方法来获得这样的接口之一:


private FooRepository getFooDataAccess() {
  return "db".equals(datasource) ? fooRepository : fooDao;
}

答案 1 :(得分:0)

为避免条件语句,您need使用通用接口 问题是FooDaoJpaRepository都不是常用界面的好选择。

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

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

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