diff --git a/src/Stubs/Doctrine/StubFilesExtensionLoader.php b/src/Stubs/Doctrine/StubFilesExtensionLoader.php
index 422f71da..05732ce3 100644
--- a/src/Stubs/Doctrine/StubFilesExtensionLoader.php
+++ b/src/Stubs/Doctrine/StubFilesExtensionLoader.php
@@ -2,10 +2,15 @@
 
 namespace PHPStan\Stubs\Doctrine;
 
+use Composer\InstalledVersions;
+use OutOfBoundsException;
 use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound;
 use PHPStan\BetterReflection\Reflector\Reflector;
 use PHPStan\PhpDoc\StubFilesExtension;
+use function class_exists;
 use function dirname;
+use function file_exists;
+use function strpos;
 
 class StubFilesExtensionLoader implements StubFilesExtension
 {
@@ -34,11 +39,18 @@ public function getFiles(): array
 			$path .= '/bleedingEdge';
 		}
 
-		$files = [
-			$path . '/DBAL/Connection.stub',
-			$path . '/ORM/QueryBuilder.stub',
-			$path . '/EntityRepository.stub',
-		];
+		$files = [];
+
+		if (file_exists($path . '/DBAL/Connection4.stub') && $this->isInstalledVersion('doctrine/dbal', 4)) {
+			$files[] = $path . '/DBAL/Connection4.stub';
+			$files[] = $path . '/DBAL/ArrayParameterType.stub';
+			$files[] = $path . '/DBAL/ParameterType.stub';
+		} else {
+			$files[] = $path . '/DBAL/Connection.stub';
+		}
+
+		$files[] = $path . '/ORM/QueryBuilder.stub';
+		$files[] = $path . '/EntityRepository.stub';
 
 		$hasLazyServiceEntityRepositoryAsParent = false;
 
@@ -62,4 +74,19 @@ public function getFiles(): array
 		return $files;
 	}
 
+	private function isInstalledVersion(string $package, int $majorVersion): bool
+	{
+		if (!class_exists(InstalledVersions::class)) {
+			return false;
+		}
+
+		try {
+			$installedVersion = InstalledVersions::getVersion($package);
+		} catch (OutOfBoundsException $e) {
+			return false;
+		}
+
+		return $installedVersion !== null && strpos($installedVersion, $majorVersion . '.') === 0;
+	}
+
 }
diff --git a/stubs/bleedingEdge/DBAL/ArrayParameterType.stub b/stubs/bleedingEdge/DBAL/ArrayParameterType.stub
new file mode 100644
index 00000000..51d291c5
--- /dev/null
+++ b/stubs/bleedingEdge/DBAL/ArrayParameterType.stub
@@ -0,0 +1,13 @@
+<?php
+
+namespace Doctrine\DBAL;
+
+enum ArrayParameterType
+{
+
+    case INTEGER;
+    case STRING;
+    case ASCII;
+    case BINARY;
+
+}
diff --git a/stubs/bleedingEdge/DBAL/Connection4.stub b/stubs/bleedingEdge/DBAL/Connection4.stub
new file mode 100644
index 00000000..0e6edd58
--- /dev/null
+++ b/stubs/bleedingEdge/DBAL/Connection4.stub
@@ -0,0 +1,68 @@
+<?php
+
+namespace Doctrine\DBAL;
+
+use Doctrine\DBAL\Cache\CacheException;
+use Doctrine\DBAL\Cache\QueryCacheProfile;
+use Doctrine\DBAL\Types\Type;
+
+/**
+ * @phpstan-type WrapperParameterType = string|Type|ParameterType|ArrayParameterType
+ * @phpstan-type WrapperParameterTypeArray = array<int<0, max>, WrapperParameterType>|array<string, WrapperParameterType>
+ */
+class Connection
+{
+    /**
+     * Executes an SQL statement with the given parameters and returns the number of affected rows.
+     *
+     * Could be used for:
+     *  - DML statements: INSERT, UPDATE, DELETE, etc.
+     *  - DDL statements: CREATE, DROP, ALTER, etc.
+     *  - DCL statements: GRANT, REVOKE, etc.
+     *  - Session control statements: ALTER SESSION, SET, DECLARE, etc.
+     *  - Other statements that don't yield a row set.
+     *
+     * This method supports PDO binding types as well as DBAL mapping types.
+     *
+     * @param literal-string                   $sql    SQL statement
+     * @param list<mixed>|array<string, mixed> $params Statement parameters
+     * @param WrapperParameterTypeArray        $types  Parameter types
+     *
+     * @return int|string The number of affected rows.
+     *
+     * @throws Exception
+     */
+    public function executeStatement($sql, array $params = [], array $types = []);
+
+    /**
+     * Executes an, optionally parameterized, SQL query.
+     *
+     * If the query is parametrized, a prepared statement is used.
+     * If an SQLLogger is configured, the execution is logged.
+     *
+     * @param literal-string                   $sql    SQL query
+     * @param list<mixed>|array<string, mixed> $params Query parameters
+     * @param WrapperParameterTypeArray        $types  Parameter types
+     *
+     * @throws Exception
+     */
+    public function executeQuery(
+        string $sql,
+        array $params = [],
+        $types = [],
+        ?QueryCacheProfile $qcp = null
+    ): Result;
+
+    /**
+     * Executes a caching query.
+     *
+     * @param literal-string                   $sql    SQL query
+     * @param list<mixed>|array<string, mixed> $params Query parameters
+     * @param WrapperParameterTypeArray        $types  Parameter types
+     *
+     * @throws CacheException
+     * @throws Exception
+     */
+    public function executeCacheQuery($sql, $params, $types, QueryCacheProfile $qcp): Result;
+
+}
diff --git a/stubs/bleedingEdge/DBAL/ParameterType.stub b/stubs/bleedingEdge/DBAL/ParameterType.stub
new file mode 100644
index 00000000..b3952099
--- /dev/null
+++ b/stubs/bleedingEdge/DBAL/ParameterType.stub
@@ -0,0 +1,16 @@
+<?php
+
+namespace Doctrine\DBAL;
+
+enum ParameterType
+{
+
+    case NULL;
+    case INTEGER;
+    case STRING;
+    case LARGE_OBJECT;
+    case BOOLEAN;
+    case BINARY;
+    case ASCII;
+
+}