diff --git a/doc/base/version/2.1-3.0.md b/doc/base/version/2.1-3.0.md index 032f4be6d..e0f5748c2 100644 --- a/doc/base/version/2.1-3.0.md +++ b/doc/base/version/2.1-3.0.md @@ -81,6 +81,10 @@ return [ * 事件名称规则统一改为全小写,为保持兼容请[参考文档](/v3.0/event/index.html#3.0%20兼容性) +### 数据库 + +* `Imi\Db\Db::getNewInstance()` 返回值改为 `Imi\ConnectionCenter\Contract\IConnection` + ### 模型 * UUID 发号器的 `type` 类型改为枚举,大小写有所变化 diff --git a/src/Components/connection-center/src/ConnectionCenter.php b/src/Components/connection-center/src/ConnectionCenter.php index d44a39ce7..07856b688 100644 --- a/src/Components/connection-center/src/ConnectionCenter.php +++ b/src/Components/connection-center/src/ConnectionCenter.php @@ -74,11 +74,23 @@ public function getConnectionManagers(): array return $this->connectionManagers; } + /** + * 获取连接. + * + * 需要调用 getInstance() 获取实际的对象进行操作. + * + * 需要自行管理连接生命周期,连接对象释放即归还连接池. + */ public function getConnection(string $name): IConnection { return $this->getConnectionManager($name)->getConnection(); } + /** + * 获取连接. + * + * 自动管理生命周期,当前上下文结束时自动释放. + */ public function getRequestContextConnection(string $name): IConnection { $requestContext = RequestContext::getContext(); @@ -119,4 +131,22 @@ public function getRequestContextConnection(string $name): IConnection return $connection; } + + /** + * 创建新的连接. + * + * 返回的连接是实际的对象,不受连接管理器管理生命周期. + */ + public function createConnection(?string $name = null, bool $autoConnect = true): mixed + { + $driver = self::getConnectionManager($name)->getDriver(); + $instance = $driver->createInstance(); + + if ($autoConnect) + { + return $driver->connect($instance); + } + + return $instance; + } } diff --git a/src/Components/connection-center/src/Facade/ConnectionCenter.php b/src/Components/connection-center/src/Facade/ConnectionCenter.php index 3feb683f6..827e803c7 100644 --- a/src/Components/connection-center/src/Facade/ConnectionCenter.php +++ b/src/Components/connection-center/src/Facade/ConnectionCenter.php @@ -15,6 +15,7 @@ * @method static IConnectionManager[] getConnectionManagers() * @method static \Imi\ConnectionCenter\Contract\IConnection getConnection(string $name) * @method static \Imi\ConnectionCenter\Contract\IConnection getRequestContextConnection(string $name) + * @method static mixed createConnection(?string $name = NULL, bool $autoConnect = true) */ #[ \Imi\Facade\Annotation\Facade(class: \Imi\ConnectionCenter\AppConnectionCenter::class) diff --git a/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php b/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php index 238a27a52..1ad8077c0 100644 --- a/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php +++ b/src/Components/connection-center/tests/Tests/ConnectionCenterTest.php @@ -198,6 +198,20 @@ public function testRequestContextDestroy(): void } } + public function testCreateConnection(): void + { + foreach (self::$names as $name) + { + $connection1 = self::$connectionCenter->createConnection($name); + $this->assertTrue($connection1->connected); + + $connection2 = self::$connectionCenter->createConnection($name, false); + $this->assertFalse($connection2->connected); + + $this->assertTrue(self::$connectionCenter->createConnection($name) !== self::$connectionCenter->createConnection($name)); + } + } + /** * @depends testNewInstance */ diff --git a/src/Components/database/src/Db.php b/src/Components/database/src/Db.php index 71569d9dd..d250479f3 100644 --- a/src/Components/database/src/Db.php +++ b/src/Components/database/src/Db.php @@ -5,6 +5,7 @@ namespace Imi\Db; use Imi\Config; +use Imi\ConnectionCenter\Contract\IConnection; use Imi\ConnectionCenter\Facade\ConnectionCenter; use Imi\Db\ConnectionCenter\DatabaseDriverConfig; use Imi\Db\Interfaces\IDb; @@ -19,28 +20,42 @@ class Db use \Imi\Util\Traits\TStaticClass; /** - * 获取新的数据库连接实例. + * 获取数据库连接实例,每个上下文中共用一个. * * @param string|null $poolName 连接池名称 * @param int $queryType 查询类型 */ - public static function getNewInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb + public static function getInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb { - $driver = ConnectionCenter::getConnectionManager(self::parsePoolName($poolName, $queryType))->getDriver(); - $instance = $driver->createInstance(); + return ConnectionCenter::getRequestContextConnection(self::parsePoolName($poolName, $queryType))->getInstance(); + } - return $driver->connect($instance); + /** + * 创建新的数据库连接实例. + * + * @param string|null $poolName 连接池名称 + * @param int $queryType 查询类型 + */ + public static function createInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb + { + return ConnectionCenter::createConnection(self::parsePoolName($poolName, $queryType)); } /** - * 获取数据库连接实例,每个RequestContext中共用一个. + * 获取新的数据库连接实例. + * + * 返回的是连接池连接对象,需调用 `getInstance()` 获取实际的对象进行操作. + * + * 连接对象释放即断开连接,操作期间需要保证连接对象不被释放. + * + * 如果不是特别必要,不推荐使用此方法!!! * * @param string|null $poolName 连接池名称 * @param int $queryType 查询类型 */ - public static function getInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IDb + public static function getNewInstance(?string $poolName = null, int $queryType = QueryType::WRITE): IConnection { - return ConnectionCenter::getRequestContextConnection(self::parsePoolName($poolName, $queryType))->getInstance(); + return ConnectionCenter::getConnection(self::parsePoolName($poolName, $queryType)); } /** diff --git a/src/Components/database/src/Listener/CheckPoolResource.php b/src/Components/database/src/Listener/CheckPoolResource.php deleted file mode 100644 index 520ae3ed7..000000000 --- a/src/Components/database/src/Listener/CheckPoolResource.php +++ /dev/null @@ -1,52 +0,0 @@ -result; - foreach ($connections as $name => $_) - { - if (!PoolManager::exists($name)) - { - try - { - $db = Db::getNewInstance($name); - if ($db->isConnected() && $db->ping()) - { - $db->close(); - } - else - { - $result = false; - } - } - catch (\Throwable $th) - { - Log::error($th); - Log::error(sprintf('The Db [%s] are not available', $name)); - $result = false; - } - } - } - } - } -}