【问题标题】:Can't create an AbstractRoutingDataSource that needs some data from another database无法创建需要来自另一个数据库的一些数据的 AbstractRoutingDataSource
【发布时间】:2013-07-07 19:47:21
【问题描述】:

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

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

现在我们想使用AbstractRoutingDataSource 构建一个解决方案。问题是:

@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 Map。但是(!)为此,我们需要存储在另一个数据库中的连接详细信息,该数据库具有自己的数据源和实体管理器。

似乎 Spring 无法确定 Bean 构造的顺序,或者我只是遗漏了一些东西。访问存储库时它总是给出NullPointerException(顺便说一句是JpaRepository)。

我们使用的是 Spring 3.2.3、Spring Data、Hibernate 4.2。 Spring 和 Spring Security 的完整 Annotation 和 Java-Code 配置。

请帮助我们!

【问题讨论】:

    标签: spring datasource


    【解决方案1】:

    Spring 当然必须调用构造函数它可以填充属性。但这不是 Spring 的东西,这是基本的 Java 101,也是使用字段注入的众多缺点之一。

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

    @Component
    class CustomRoutingDataSource extends AbstractRoutingDataSource {
    
      @Autowired
      public CustomRoutingDataSource(DbDetailsRepository repo, Environment environment) {
        …
      }
      …
    }
    

    【讨论】:

    • 是的,当然...有时我们看不到最明显的东西
    猜你喜欢
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-13
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多