diff --git a/node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt
index b8389d10a8..1c21e14617 100644
--- a/node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt
+++ b/node/src/integration-test/kotlin/net/corda/node/services/vault/VaultQueryIntegrationTests.kt
@@ -13,45 +13,20 @@ package net.corda.node.services.vault
 
 import net.corda.core.identity.CordaX500Name
 import net.corda.testing.core.TestIdentity
-import net.corda.testing.internal.IntegrationTest
-import net.corda.testing.internal.IntegrationTestSchemas
-import net.corda.testing.internal.toDatabaseSchemaName
+import net.corda.testing.internal.*
 import org.junit.*
+import org.junit.rules.RuleChain
 
-@Ignore // TODO - refactor VaultQuery integration tests with external junit resource
-class VaultQueryIntegrationTests : VaultQueryTests() {
-
-    private val adapter = object: IntegrationTest() {
-    }
-
-    @Before
-    override fun setUp() {
-        adapter.setUp()
-        super.setUp()
-    }
-
-    @After
-    override fun tearDown() {
-        adapter.tearDown()
-        super.tearDown()
-    }
+class VaultQueryIntegrationTests : VaultQueryTestsBase(), VaultQueryParties by vaultQueryTestRule {
 
     companion object {
         val MEGA_CORP = TestIdentity(CordaX500Name("MegaCorp", "London", "GB")).name
-        @ClassRule
-        @JvmField
-        val databaseSchemas = IntegrationTestSchemas(MEGA_CORP.toDatabaseSchemaName())
+        val databaseSchemas = listOf(Companion.MEGA_CORP.toDatabaseSchemaName())
 
-        @BeforeClass
-        @JvmStatic
-        fun globalSetUp() {
-            IntegrationTest.globalSetUp()
-        }
+        val globalDatabaseRule = GlobalDatabaseRule(databaseSchemas)
+        val vaultQueryTestRule = VaultQueryTestRule()
 
-        @AfterClass
-        @JvmStatic
-        fun globalTearDown() {
-            IntegrationTest.globalTearDown()
-        }
+        @ClassRule @JvmField
+        val ruleChain = RuleChain.outerRule(globalDatabaseRule).around(vaultQueryTestRule)
     }
 }
diff --git a/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java b/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java
index 783a55b060..7619517b4f 100644
--- a/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java
+++ b/node/src/test/java/net/corda/node/services/vault/VaultQueryJavaTests.java
@@ -29,8 +29,8 @@ import net.corda.core.node.services.vault.QueryCriteria.VaultCustomQueryCriteria
 import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria;
 import net.corda.finance.contracts.DealState;
 import net.corda.finance.contracts.asset.Cash;
+import net.corda.finance.sampleschemas.SampleCashSchemaV2;
 import net.corda.finance.schemas.CashSchemaV1;
-import net.corda.finance.schemas.SampleCashSchemaV2;
 import net.corda.node.services.api.IdentityServiceInternal;
 import net.corda.nodeapi.internal.persistence.CordaPersistence;
 import net.corda.nodeapi.internal.persistence.DatabaseTransaction;
diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryExceptionsTests.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryExceptionsTests.kt
index 09fc08a053..d67ae7475a 100644
--- a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryExceptionsTests.kt
+++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryExceptionsTests.kt
@@ -18,9 +18,6 @@ import net.corda.finance.*
 import net.corda.finance.contracts.asset.Cash
 import net.corda.finance.sampleschemas.SampleCashSchemaV3
 import net.corda.finance.schemas.CashSchemaV1
-import net.corda.nodeapi.internal.persistence.CordaPersistence
-import net.corda.nodeapi.internal.persistence.DatabaseTransaction
-import net.corda.finance.schemas.SampleCashSchemaV3
 import net.corda.testing.core.*
 import net.corda.testing.internal.vault.DummyLinearStateSchemaV1
 import org.assertj.core.api.Assertions.assertThatThrownBy
@@ -48,10 +45,6 @@ class VaultQueryExceptionsTests : VaultQueryParties by rule {
     @JvmField
     val expectedEx: ExpectedException = ExpectedException.none()
 
-    @Rule
-    @JvmField
-    val rollbackRule = VaultQueryRollbackRule(this)
-
     @Test
     fun `query attempting to use unregistered schema`() {
         database.transaction {
diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
index 280000823d..9f3f09f32f 100644
--- a/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
+++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultQueryTests.kt
@@ -28,12 +28,11 @@ import net.corda.finance.contracts.Commodity
 import net.corda.finance.contracts.DealState
 import net.corda.finance.contracts.asset.Cash
 import net.corda.finance.contracts.asset.cash.selection.AbstractCashSelection
+import net.corda.finance.sampleschemas.SampleCashSchemaV2
 import net.corda.finance.sampleschemas.SampleCashSchemaV3
 import net.corda.finance.schemas.CashSchemaV1
 import net.corda.finance.schemas.CashSchemaV1.PersistentCashState
 import net.corda.finance.schemas.CommercialPaperSchemaV1
-import net.corda.finance.schemas.SampleCashSchemaV2
-import net.corda.finance.schemas.SampleCashSchemaV3
 import net.corda.node.internal.configureDatabase
 import net.corda.nodeapi.internal.persistence.CordaPersistence
 import net.corda.nodeapi.internal.persistence.DatabaseConfig
@@ -159,11 +158,6 @@ open class VaultQueryTestRule : ExternalResource(), VaultQueryParties {
         (notaryServices.myInfo.legalIdentitiesAndCerts + BOC_IDENTITY + CASH_NOTARY_IDENTITY + MINI_CORP_IDENTITY + MEGA_CORP_IDENTITY).forEach { identity ->
             services.identityService.verifyAndRegisterIdentity(identity)
         }
-
-        @AfterClass @JvmStatic
-        fun afterClass() {
-            database.close()
-        }
     }
 
     override fun after() {
diff --git a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/IntegrationTest.kt b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/IntegrationTest.kt
index f25e5a2bef..16ee253e6c 100644
--- a/testing/test-utils/src/main/kotlin/net/corda/testing/internal/IntegrationTest.kt
+++ b/testing/test-utils/src/main/kotlin/net/corda/testing/internal/IntegrationTest.kt
@@ -18,6 +18,29 @@ import org.junit.Before
 import org.junit.BeforeClass
 import org.junit.rules.ExternalResource
 
+sealed class DatabaseRule(val databaseSchemas: List<String>, val dbScriptPrefix: String) : ExternalResource() {
+
+    private val DATABASE_PROVIDER = "custom.databaseProvider"
+    private val dbProvider = System.getProperty(DATABASE_PROVIDER, "")
+    private val TEST_DB_SCRIPT_DIR = "test.db.script.dir"
+    private val testDbScriptDir = System.getProperty(TEST_DB_SCRIPT_DIR, "database-scripts")
+
+    public override fun before() {
+        if (dbProvider.isNotEmpty()) {
+            runDbScript(dbProvider,"$testDbScriptDir/$dbScriptPrefix-cleanup.sql", databaseSchemas)
+            runDbScript(dbProvider,"$testDbScriptDir/$dbScriptPrefix-setup.sql", databaseSchemas)
+        }
+    }
+    public override fun after() {
+        if (dbProvider.isNotEmpty()) {
+            runDbScript(dbProvider,"$testDbScriptDir/$dbScriptPrefix-cleanup.sql", databaseSchemas)
+        }
+    }
+}
+
+class GlobalDatabaseRule(databaseSchemas: List<String> = emptyList()) : DatabaseRule(databaseSchemas, "db-global")
+class LocalDatabaseRule(databaseSchemas: List<String> = emptyList()) : DatabaseRule(databaseSchemas, "db")
+
 /**
  * Base class for all integration tests that require common setup and/or teardown.
  * eg. serialization, database schema creation and data population / clean-up