【问题标题】:Handling Dynamic Database Connections处理动态数据库连接
【发布时间】:2017-03-16 17:08:25
【问题描述】:

我的应用程序要求是动态创建数据库连接。数据库连接详细信息在编译时未知,仅在运行时提供给应用程序。处理一个请求只需要一个连接,连接范围仅取决于请求执行周期。同一用户可能会或可能不会发布包含数据库连接详细信息的新请求。我们可以有数百个这样的用户,因此如果假设他们都同时发布请求,我的应用程序将不得不创建数百个这样的数据库连接。

基于这种情况,我有以下问题/需要澄清-

  1. 连接池在这里不起作用,因为数据库连接是 动态的?
  2. 在这种情况下创建数据库连接的最佳方法是什么?这里最好使用纯 JDBC 连接?
  3. 为每个请求创建休眠会话工厂,仅仅创建一个连接会导致开销吗?或者我们可以这样做吗?
  4. 还有哪些其他可能的好方法来处理这种情况?

编辑: 我的应用程序是一个更大的 Web 应用程序的一个组件。这个更大的 Web 应用程序在云上拥有自己的存储空间。任何用户都可以在此存储上创建沙箱。因此,在请求数据加载时,用户必须传递凭据。

我是休眠和春季的新手。请帮助我为此确定最佳架构。

【问题讨论】:

  • 您在哪里配置数据源详细信息?属性文件? xml文件?它们在运行时来自单独的服务吗?
  • 主机名、端口号等数据库详细信息存储在后端数据库中。但是,用户名、密码等用户架构详细信息会随用户请求一起传递。
  • 所以您要为每个用户创建一个架构?
  • 如果只有在运行时才知道数据库连接,您为什么认为需要 Hibernate?运行用户提供的 SQL 查询?或者您以某种方式事先知道实体,即使您不知道数据库将在哪里?我不明白。
  • 这并不是不可能的。但是我想知道这背后的想法是什么,因为它毕竟可能是一个非常可怕的想法。这里的很多人(他们经常会帮助告知他们对某事)花时间担心他们是否可以而不是是否应该。

标签: java hibernate jdbc spring-jdbc


【解决方案1】:

我认为您可能会发现 Open Session in View 模式对您的用例很有趣。您只需要取消 private SessionFactory sf; 字段并在每次调用时构建一个新字段。

或者,如果您有一个大堆并且同一用户多次调用的可能性很大,您可以实现某种静态 HashMap,将给定用户与给定 SessionFactory 相关联,并在已经存在的情况下重用它。

那么关于你的问题:

  1. 除非您自己实现连接池,否则无法实现连接池。但在考虑之前,先问问自己,同一个用户是否有可能同时需要多个连接。
  2. 我认为我建议的解决方案是最差的,前提是您需要 hibernate 支持来管理您的实体
  3. 它会导致开销,除了在框架中进行黑客攻击之外,没有其他方法可以解决可能产生不良副作用的问题。例如,您可以想象使用ThreadLocal 将 SessionFactory 分配给每个线程(来自 tomcat 管理的池),然后在每次调用时,设置与用户对应的数据源,请参见下面的代码
  4. 您必须提供更多有关您的应用程序及其内部的详细信息,然后我才能(也许)就这一点向您提供建议。

这是我在 3 中谈到的代码。请记住,这是糟糕的设计。我还采取了一些捷径来使这个技巧很快就可以理解。不知道它是否真的有效,但你可以试一试

public class HibernateSessionRequestFilter implements Filter {

    private static Logger log = LoggerFactory.getLogger(HibernateSessionRequestFilter.class);
    private static ThreadLocal<LocalSessionFactoryBean> lsfbth = new ThreadLocal<LocalSessionFactoryBean>();
    private static final Map<Object, DataSource> datasourceMap = new HashMap<>();

    public void init(FilterConfig filterConfig) throws ServletException {
        log.debug("Initializing filter...");
        LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean();
        lsfb.setHibernateProperties(null); // TODO: add correct values
        lsfbth.set(lsfb);
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {

        LocalSessionFactoryBean lsfb = lsfbth.get();
        String credentials = null; //TODO: get user login from request
        DataSource dataSource = datasourceMap.get(credentials);
        if( dataSource==null){
            // TODO: build datasource here
            datasourceMap.put(credentials, dataSource);
        }
        lsfb.setDataSource(dataSource);
        SessionFactory sf = lsfb.getObject();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-22
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2015-08-09
    • 2010-12-25
    • 2016-07-05
    相关资源
    最近更新 更多