自另一个数据库的某些数据的AbstractRoutingData

自另一个数据库的某些数据的AbstractRoutingData

本文介绍了无法创建需要来自另一个数据库的某些数据的AbstractRoutingDataSource的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们当前有一个应用程序,该应用程序使用具有相同模式的多个数据库。目前,我们正在使用自定义解决方案来根据用户的会话在它们之间进行切换。这可以通过

We currently have an application which uses multiple databases with the same schema. At the moment we're using a custom solution for switching between them based on the user's session. This works via

public final class DataSourceProxy extends BasicDataSource {

    ...

    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    if (auth != null && auth.getDetails() instanceof Map) {

        Map<String, String> details = (Map<String, String>) auth.getDetails();
        String targetUrl = details.get("database");

        Connection c = super.getConnection();
        Statement  s = c.createStatement();
        s.execute("USE " + targetUrl + ";");
        s.close();
        return c;
    } else {
        return super.getConnection();
    }
}

现在我们要使用<$ c构建解决方案$ c> AbstractRoutingDataSource 。问题是:

Now we want to build a solution using AbstractRoutingDataSource. The problem is:

@Component
public class CustomRoutingDataSource extends AbstractRoutingDataSource {
    @Autowired
    Environment env;

    @Autowired
    DbDetailsRepositoy repo;

    public CustomRoutingDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
        for(DBDetails dbd : repo.findAll() {
            // create DataSource and put it into the map
        }
        setTargetDataSources(new HashMap<Object, Object>());
    }

    @Override
    protected Object determineCurrentLookupKey() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null && auth.getDetails() instanceof Map) {
            Map<String, String> details = (Map<String, String>) auth.getDetails();
            return details.get("database");
        }
        return null;
    }
}

在构造函数内部(甚至通过 @PostConstruct ),我们必须填充 targetDataSources地图但是(!)为此,我们需要将连接详细信息存储在另一个数据库中,该数据库具有自己的数据源和实体管理器。

Inside the constructor (or even via @PostConstruct) we have to fill the targetDataSources Map. But(!) for this we need the connection details which are stored in another database, which has its own DataSource and Entity Manager.

无法确定Bean的构造顺序,或者我只是想念一些东西。在访问存储库时,它总是给出 NullPointerException (btw是 JpaRepository )。

It seems like Spring can't determine the order of Bean construction, or maybe I'm just missing something. It always gives a NullPointerException when accessing the repository (which btw is a JpaRepository).

我们正在使用Spring 3.2.3,Spring Data,Hibernate 4.2。完整的Spring和Spring Security注释和Java代码配置。

We're using Spring 3.2.3, Spring Data, Hibernate 4.2. Complete Annotation and Java-Code configuration of Spring and Spring Security.

请帮助我们!

推荐答案

Spring当然必须在其可以填充属性之前调用构造函数。但这不是Spring的事情,那是Java 101的基本知识,也是使用字段注入的众多缺点之一。

Spring of course has to call the constructor before it can populate the properties. But that's not a Spring thing, that's basic Java 101 and one of the plenty downsides of using field injection.

要避免这种情况,只需将依赖项添加到构造函数中:

To avoid this, simply add your dependencies to the constructor:

@Component
class CustomRoutingDataSource extends AbstractRoutingDataSource {

  @Autowired
  public CustomRoutingDataSource(DbDetailsRepository repo, Environment environment) {
    …
  }
  …
}

这篇关于无法创建需要来自另一个数据库的某些数据的AbstractRoutingDataSource的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 07:17