Java の基本
JVM 向けの pgmem には、クライアントの io.github.shibukawa.pgmem:pgmem、テスト用モジュールの pgmem-junit5、pgmem-spring、pgmem-micronaut、プラットフォームごとの classifier でバイナリを配る pgmem-native があります。クライアントはサードパーティの実行時依存を持たないので、JDBC ドライバは自分で追加してください。
val pgmemOs = System.getProperty("os.name").lowercase()val pgmemArch = System.getProperty("os.arch").lowercase()val pgmemPlatform = when { pgmemOs.contains("mac") || pgmemOs.contains("darwin") -> "darwin" pgmemOs.contains("win") -> "windows" pgmemOs.contains("linux") -> "linux" else -> error("Unsupported OS: $pgmemOs; use PGMEM_BINARY")}val pgmemCpu = when (pgmemArch) { "amd64", "x86_64" -> "x86_64" "aarch64", "arm64" -> "arm64" else -> error("Unsupported architecture: $pgmemArch; use PGMEM_BINARY")}val pgmemNative = "$pgmemPlatform-$pgmemCpu"
dependencies { testImplementation("io.github.shibukawa.pgmem:pgmem-junit5:1.18.0") // io.github.shibukawa.pgmem:pgmem も入る testRuntimeOnly("io.github.shibukawa.pgmem:pgmem-native:1.18.0:$pgmemNative") // 自分のプラットフォーム用のバイナリ testRuntimeOnly("org.postgresql:postgresql:42.7.7") testImplementation(platform("org.junit:junit-bom:5.14.0")) testImplementation("org.junit.jupiter:junit-jupiter") testRuntimeOnly("org.junit.platform:junit-platform-launcher")}
tasks.test { useJUnitPlatform()}def pgmemOs = System.getProperty('os.name').toLowerCase()def pgmemArch = System.getProperty('os.arch').toLowerCase()def pgmemPlatform = pgmemOs.contains('mac') || pgmemOs.contains('darwin') ? 'darwin' : pgmemOs.contains('win') ? 'windows' : pgmemOs.contains('linux') ? 'linux' : nulldef pgmemCpu = ['amd64', 'x86_64'].contains(pgmemArch) ? 'x86_64' : ['aarch64', 'arm64'].contains(pgmemArch) ? 'arm64' : nullif (!pgmemPlatform || !pgmemCpu) throw new GradleException('Unsupported host; use PGMEM_BINARY')def pgmemNative = "${pgmemPlatform}-${pgmemCpu}"
dependencies { testImplementation 'io.github.shibukawa.pgmem:pgmem-junit5:1.18.0' // io.github.shibukawa.pgmem:pgmem も入る testRuntimeOnly "io.github.shibukawa.pgmem:pgmem-native:1.18.0:${pgmemNative}" // 自分のプラットフォーム用のバイナリ testRuntimeOnly 'org.postgresql:postgresql:42.7.7' testImplementation platform('org.junit:junit-bom:5.14.0') testImplementation 'org.junit.jupiter:junit-jupiter' testRuntimeOnly 'org.junit.platform:junit-platform-launcher'}
test { useJUnitPlatform()}<dependencies> <dependency> <groupId>io.github.shibukawa.pgmem</groupId> <artifactId>pgmem-junit5</artifactId> <version>1.18.0</version> <scope>test</scope> </dependency> <dependency> <groupId>io.github.shibukawa.pgmem</groupId> <artifactId>pgmem-native</artifactId> <version>1.18.0</version> <classifier>${pgmem.native.classifier}</classifier> <scope>test</scope> </dependency> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.7.7</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.14.0</version> <scope>test</scope> </dependency></dependencies>classifier は linux-x86_64、linux-arm64、darwin-arm64、windows-x86_64、windows-arm64 です。複数のプラットフォームでビルドするなら、5 つ全部に依存するのではなく、Maven のプロファイルや Gradle の OS 判定プラグインでプラットフォームごとに 1 つを選んでください。バイナリは初回に ~/.cache/pgmem/<version>/ へ展開されます。Java 17 以降が必要です。
Gradle の例は実行ホストから classifier を選びます。Maven では mvn -Dpgmem.native.classifier=linux-x86_64 test のように指定してください。複数ホストで使う場合は、下の profiles を POM に追加すると自動選択できます。Intel Mac 向けの native artifact はありません。その場合は native 依存を省き、ローカルビルドの PGMEM_BINARY を指定します。
Maven の既存設定が JUnit 5 に対応していない場合は、次の build 設定も追加します。
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.14.0</version> <configuration><release>17</release></configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.5.4</version> </plugin> </plugins></build>Maven profiles
<profiles> <profile> <id>pgmem-linux-amd64</id> <activation><os><name>Linux</name><arch>amd64</arch></os></activation> <properties><pgmem.native.classifier>linux-x86_64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-linux-x86_64</id> <activation><os><name>Linux</name><arch>x86_64</arch></os></activation> <properties><pgmem.native.classifier>linux-x86_64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-linux-aarch64</id> <activation><os><name>Linux</name><arch>aarch64</arch></os></activation> <properties><pgmem.native.classifier>linux-arm64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-linux-arm64</id> <activation><os><name>Linux</name><arch>arm64</arch></os></activation> <properties><pgmem.native.classifier>linux-arm64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-darwin-aarch64</id> <activation><os><family>mac</family><arch>aarch64</arch></os></activation> <properties><pgmem.native.classifier>darwin-arm64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-darwin-arm64</id> <activation><os><family>mac</family><arch>arm64</arch></os></activation> <properties><pgmem.native.classifier>darwin-arm64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-windows-amd64</id> <activation><os><family>windows</family><arch>amd64</arch></os></activation> <properties><pgmem.native.classifier>windows-x86_64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-windows-x86_64</id> <activation><os><family>windows</family><arch>x86_64</arch></os></activation> <properties><pgmem.native.classifier>windows-x86_64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-windows-aarch64</id> <activation><os><family>windows</family><arch>aarch64</arch></os></activation> <properties><pgmem.native.classifier>windows-arm64</pgmem.native.classifier></properties> </profile> <profile> <id>pgmem-windows-arm64</id> <activation><os><family>windows</family><arch>arm64</arch></os></activation> <properties><pgmem.native.classifier>windows-arm64</pgmem.native.classifier></properties> </profile></profiles>-
プロセスを起動します。
PgmemはAutoCloseableで、閉じるとすべてのサーバーが止まります。try (Pgmem pg = Pgmem.builder().database("app").start()) {Server template = pg.template();System.out.println(template.jdbcUrl()); // jdbc:postgresql://127.0.0.1:54321/app?user=postgres&sslmode=disable}Pgmem.builder().database("app").start().use { pg ->val template = pg.template()println(template.jdbcUrl())}ビルダーにはほかに
user(...)、param("shared_buffers", "128MB")、log(true)、binary(path)があります。 -
スキーマを登録します。 マイグレーションツールを使います。マイグレーションツールを参照してください。
-
シードデータを入れます。 シードデータを参照してください。
-
JDBC で使います。
jdbcUrl()にはユーザーとsslmodeが含まれ、dataSource()はjavax.sql.DataSourceを返します。try (Connection conn = DriverManager.getConnection(template.jdbcUrl());PreparedStatement ps = conn.prepareStatement("SELECT name FROM users WHERE id = ?")) {ps.setLong(1, 1);try (ResultSet rs = ps.executeQuery()) {rs.next();String name = rs.getString(1);}}DriverManager.getConnection(template.jdbcUrl()).use { conn ->conn.prepareStatement("SELECT name FROM users WHERE id = ?").use { ps ->ps.setLong(1, 1)ps.executeQuery().use { rs -> rs.next(); println(rs.getString(1)) }}}この URL で HikariCP のプールを作ることもできます。接続ごとにバックエンドプロセスが起動します。
マイグレーションツール
Section titled “マイグレーションツール”String schema = Files.readString(Path.of("src/test/resources/schema.sql"));try (Connection conn = DriverManager.getConnection(template.jdbcUrl()); Statement st = conn.createStatement()) { st.execute(schema);}Flyway.configure() .dataSource(template.jdbcUrl(), template.user(), null) .locations("classpath:db/migration") .load() .migrate();Flyway 10 以降では、テストのクラスパスに org.flywaydb:flyway-database-postgresql も必要です。
try (Connection conn = DriverManager.getConnection(template.jdbcUrl())) { Database db = DatabaseFactory.getInstance() .findCorrectDatabaseImplementation(new JdbcConnection(conn)); new CommandScope("update") .addArgumentValue("database", db) .addArgumentValue("changelogFile", "db/changelog/db.changelog-master.yaml") .execute();}シードデータ
Section titled “シードデータ”<dataset> <users id="1" name="Frank" email="frank@example.com"/> <users id="2" name="Grace" email="grace@example.com"/> <orders id="1" user_id="1" amount="1200"/></dataset>IDatabaseTester tester = new JdbcDatabaseTester( "org.postgresql.Driver", template.jdbcUrl(), template.user(), "");tester.setDataSet(new FlatXmlDataSetBuilder() .build(getClass().getResourceAsStream("/seed.xml")));tester.setSetUpOperation(DatabaseOperation.CLEAN_INSERT);tester.onSetup();try (Connection conn = DriverManager.getConnection(template.jdbcUrl()); Statement st = conn.createStatement()) { st.execute(Files.readString(Path.of("src/test/resources/seed.sql")));}try (Connection conn = DriverManager.getConnection(template.jdbcUrl())) { CopyManager copy = conn.unwrap(PGConnection.class).getCopyAPI(); copy.copyIn("COPY users (id, name, email) FROM STDIN (FORMAT csv)", new StringReader("1,Frank,frank@example.com\n2,Grace,grace@example.com\n"));}スナップショットとフォークを直接使う
Section titled “スナップショットとフォークを直接使う”try (Pgmem pg = Pgmem.builder().database("app").start()) { migrate(pg.template().jdbcUrl()); Snapshot snap = pg.template().snapshot(); // 開いているトランザクションを待つ。30 秒 try (Fork fork = snap.fork()) { // 専用の複製 DataSource ds = fork.dataSource(); // ... }}snapshot() の前に、テンプレートへの接続はすべてコミットするか閉じてください。次のページの JUnit 5 拡張は、これをテストのライフサイクルに組み込みます。