对同一模型使用多个数据库

问题描述

我正在研究一些需要连接到两个单独的数据库的API,这些数据库包含相似的表但数据不同。

我已经在app.PHPapp_local.PHP中配置了两个数据源,并且两个数据源都是可以访问的。

通过一些研究,我发现ConnectionManager::alias应该是我所需要的,因此我想到了:

// Fetching `energy` DB data
ConnectionManager::alias('energy','default');
$energy = $this->Users->find()->first();
debug($energy);
ConnectionManager::dropAlias('default');

// Fetching `default` (gas) DB data
$gas = $this->Users->find()->first();
debug($gas);

问题是,如果我像这样运行那些查询,则调试将提供相同的数据,这意味着energy数据库中的数据将被打印两次。

但是:

  • 如果我仅运行energy,则会发现它为我提供了来自能源数据库的正确结果。
  • 如果我只运行gas,它会为我提供气体数据库中的正确结果。

看起来只有第一个数据源实际上在使用。

我做错了什么?

解决方法

实例化表类后,它将保存实例化时分配给它的连接实例(connection的{​​{1}}选项)和表实例时创建的实例。首先尝试获取连接(\Cake\ORM\Table::__construct())。

因此,仅删除别名是不会做任何事情的,表上的下一次调用将使用表已保存的连接实例,而不会尝试再次自行获得连接。

由于您希望更改连接影响所有内容,因此必须在删除连接别名后清除表注册表,然后再次加载表,以便使用实际的\Cake\ORM\Table::getConnection()连接再次创建表(如果您只想影响特定的实例,则可以通过default分配一个新的连接实例)。为了避免在创建别名时遇到与已经创建的表实例相同的问题,您很可能还应该在那个之后清除注册表。

基本示例:

setConnection()

如您所见,这不仅需要再次加载模型/表,而且还需要在属性上取消设置实例,否则ConnectionManager::alias('energy','default'); $this->getTableLocator()->clear(); // table instances created after this point will respect the alias $this->Users = null; $this->loadModel('Users'); $energy = $this->Users->find()->first(); ConnectionManager::dropAlias('default'); $this->getTableLocator()->clear(); // table instances created after this point will use the non-aliased connection $this->Users = null; $this->loadModel('Users'); $gas = $this->Users->find()->first(); 不会实际加载表,而是返回该实例。已在loadModel()属性上设置。

我建议您切换到通过表定位器(甚至在控制器中)来获取模型,那样您就可以跳过这些笨拙的未设置内容,并降低了意外访问存储在{{1 }}:

$this->Users

您可能还应该考虑在服务的某个位置集中此连接交换。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...