tamuです。

Heroku ConnectでSalesforceのレコードを参照できるようになったので、 Ruby on Railsからその情報を扱ってみたいと思います。

例によって開発はローカル環境で行いたいので、環境構築のお話をしていきます。

環境について

Heroku Connectを有効にしたHerokuはこのような環境になります。

Heroku側のスキーマ

xxxxx データベース(herokuが自動で命名する)の中に public スキーマと、 Salesforce側のデータをいじくることができる salesforce スキーマがあります。

これと同じような環境をローカルでも構築します。

また、salesforce スキーマで定義するテーブルの情報(SQL)は、ローカルで開発するHeroku Connect を参考に取得します。

方針

migrationはFlywayを使います。

Ruby on Railsで開発するHeroku Connect」と同様に、 手作業での環境設定はやらないようにします。

今回は maven を使うので mvn xxxx で済むようにしていきます。

flywayの設定

ローカル環境で開発する際は自動でmigrationするように、Heroku環境で動かす場合はデプロイ時にmigrationするように設定していきます。

src/main/resources/application.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
spring:
  datasource:
    driver-class-name: org.postgresql.Driver
  profiles:
    active: local
  sql:
   init:
     enabled: false
mybatis:
  configuration:
    map-underscore-to-camel-case: true

---
# local development
spring:
  config:
    activate:
      on-profile: local
  datasource:
    url: jdbc:postgresql://localhost:5432/herokuconn
    username: root
    password: password
  flyway:
    enabled: true
    url: jdbc:postgresql://localhost:5432/herokuconn
    user: root
    password: password
    baseline-on-migrate: true
    baseline-version: 1.0.0
    baseline-description: Initial
    schemas:
      - public
    locations:
      - classpath:db/migration
      - classpath:db/heroku
---
# run on heroku
spring:
  config:
    activate:
      on-profile: heroku
  datasource:
    maxActive: 10
    maxIdle: 5
    minIdle: 2
    initialSize: 5
    removeAbandoned: true
    url: ${JDBC_DATABASE_URL}
    username: ${JDBC_DATABASE_USERNAME}
    password: ${JDBC_DATABASE_PASSWORD}

マルチプロファイルで定義しています。

localプロファイル

localプロファイルを見てみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
spring:
  ..(省略)..
  flyway:
    enabled: true
    ..(省略)..
    schemas:
      - public
    locations:
      - classpath:db/migration
      - classpath:db/heroku

spring.flyway.enabledtrue なので Spring 起動時に migration が動くこととなります。 ( mvn test でテスト実施時に Spring が起動し、migration が行われます)

spring.flyway.locations に定義している場所から migration 用のSQLを持ってきています。

db/migration が通常のアプリケーションで使う migration で、 db/heroku が Heroku Connect の環境を作るための migration です。

herokuプロファイル

つづいてherokuプロファイルを見てみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
spring:
  config:
    activate:
      on-profile: heroku
  datasource:
    maxActive: 10
    maxIdle: 5
    minIdle: 2
    initialSize: 5
    removeAbandoned: true
    url: ${JDBC_DATABASE_URL}
    username: ${JDBC_DATABASE_USERNAME}
    password: ${JDBC_DATABASE_PASSWORD}

これはHeroku上(本番環境)で動かすことを想定したプロファイルですが、とくに migration に関する設定は何も書いていません。 Spring 起動時は接続先のデータベースをそのまま使うだけになります。

migration はデプロイ時に行うため、アプリケーションを一つ用意します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package com.sample.herokudemo.migration;

import org.flywaydb.core.Flyway;

/**
 * heroku 上のデータベースをmigrationする
 */
public class Migrations {
    public static void main(String...args) throws Exception {
        Flyway flyway = Flyway.configure().dataSource(System.getenv("JDBC_DATABASE_URL"),
                System.getenv("JDBC_DATABASE_USERNAME"),
                System.getenv("JDBC_DATABASE_PASSWORD")).load();

        // start the migration
        flyway.migrate();
    }
}

これを実行すると環境変数からデータベース接続に必要な情報を取得し、Flyway が migration を行います。

デプロイ時に実行されるように Procfile に定義を書いておきます。

migrate: java -cp target/herokudemo-0.0.1-SNAPSHOT.jar.original:target/dependency/* com.sample.herokudemo.migration.Migrations
web: java -jar target/herokudemo-0.0.1-SNAPSHOT.jar --spring.profiles.active=heroku --server.port=$PORT

これで、ローカル開発時は起動時に migration が、Heroku で動かす際はデプロイ時に migration が動くようになります。

salesforceスキーマの作成

/docker-entrypoint-initdb.d でスキーマを作っても良いのですが、 salesforceスキーマに関することは db/heroku 下の定義に統一したいと思います。

V1_yyyymmdd_hhmmss_create_schema_salesforce.sql

1
CREATE SCHEMA salesforce;

salesforceスキーマ内のテーブル作成

salesforceスキーマの作成と同じく、migrationで行います。

V1_yyyymmdd_hhmmss_create_product2.sql

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
CREATE TABLE salesforce.product2 (
    externalproductid__c character varying(255),
    family character varying(255),
    externalid character varying(255),
    lastvieweddate timestamp without time zone,
    stockkeepingunit character varying(180),
    name character varying(255),
    externaldatasourceid character varying(18),
    displayurl character varying(1000),
    lastmodifieddate timestamp without time zone,
    isdeleted boolean,
    isactive boolean,
    systemmodstamp timestamp without time zone,
    lastmodifiedbyid character varying(18),
    createddate timestamp without time zone,
    quantityunitofmeasure character varying(255),
    createdbyid character varying(18),
    productcode character varying(255),
    description character varying(4000),
    lastreferenceddate timestamp without time zone,
    sfid character varying(18) COLLATE pg_catalog.ucs_basic,
    id integer NOT NULL,
    _hc_lastop character varying(32),
    _hc_err text
);
CREATE SEQUENCE salesforce.product2_id_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER SEQUENCE salesforce.product2_id_seq OWNED BY salesforce.product2.id;
ALTER TABLE ONLY salesforce.product2 ALTER COLUMN id SET DEFAULT nextval('salesforce.product2_id_seq'::regclass);
ALTER TABLE ONLY salesforce.product2
    ADD CONSTRAINT product2_pkey PRIMARY KEY (id);
CREATE INDEX hc_idx_product2_lastmodifieddate ON salesforce.product2 USING btree (lastmodifieddate);
CREATE INDEX hc_idx_product2_systemmodstamp ON salesforce.product2 USING btree (systemmodstamp);
CREATE UNIQUE INDEX hcu_idx_product2_externalproductid__c ON salesforce.product2 USING btree (externalproductid__c);
CREATE UNIQUE INDEX hcu_idx_product2_sfid ON salesforce.product2 USING btree (sfid);

その他

MyBatisを使うのであれば、search_pathに追加しなくてもそのまま使えます。

実際の動作

dockerを起動し、migrationを実行するとことまでやってみます。

dockerの起動

docker-compose.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
version: "3"
services:
  dbserver:
    image: postgres:12
    container_name: herokuconndb
    ports:
      - 5432:5432
    environment:
      POSTGRES_USER: root
      POSTGRES_PASSWORD: password
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
    volumes:
      - database:/var/lib/postgresql/data
volumes:
  database:
    driver: local
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
docker compose up
[+] Running 2/2
 ⠿ Volume "heroku-connect-demo_database"  Created                                                                                                                                                         0.1s
 ⠿ Container herokuconnectdb              Started                                                                                                                                                         1.2s
Attaching to herokuconnectdb
herokuconnectdb  | The files belonging to this database system will be owned by user "postgres".
herokuconnectdb  | This user must also own the server process.
herokuconnectdb  | 
herokuconnectdb  | The database cluster will be initialized with locale "en_US.utf8".
herokuconnectdb  | The default text search configuration will be set to "english".
herokuconnectdb  | 
...
...
herokuconnectdb  | PostgreSQL init process complete; ready for start up.
herokuconnectdb  | 
herokuconnectdb  | 2021-08-14 04:37:33.803 UTC [1] LOG:  starting PostgreSQL 12.8 (Debian 12.8-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
herokuconnectdb  | 2021-08-14 04:37:33.803 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
herokuconnectdb  | 2021-08-14 04:37:33.803 UTC [1] LOG:  listening on IPv6 address "::", port 5432
herokuconnectdb  | 2021-08-14 04:37:33.805 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
herokuconnectdb  | 2021-08-14 04:37:33.815 UTC [76] LOG:  database system was shut down at 2021-08-14 04:37:33 UTC
herokuconnectdb  | 2021-08-14 04:37:33.819 UTC [1] LOG:  database system is ready to accept connections

ビルド時のmigration

mavenでビルドを行います。 pom.xml で特殊なことはやっていません。

pom.xml

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.4.3</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.sample.herokudemo</groupId>
	<artifactId>herokudemo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>herokudemo</name>
	<description>heroku connect demo</description>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-rest</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.4</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-ui</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>org.springdoc</groupId>
			<artifactId>springdoc-openapi-data-rest</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf</artifactId>
			<version>3.0.11.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.thymeleaf</groupId>
			<artifactId>thymeleaf-spring5</artifactId>
			<version>3.0.11.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.flywaydb</groupId>
			<artifactId>flyway-maven-plugin</artifactId>
			<version>7.7.0</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals><goal>copy</goal></goals>
						<configuration>
							<artifactItems>
								<artifactItem>
									<groupId>org.flywaydb</groupId>
									<artifactId>flyway-core</artifactId>
									<version>7.7.0</version>
									<destFileName>flyway.jar</destFileName>
								</artifactItem>
								<artifactItem>
									<groupId>org.postgresql</groupId>
									<artifactId>postgresql</artifactId>
									<destFileName>postgres.jar</destFileName>
								</artifactItem>
							</artifactItems>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

mavenでビルドします。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
$ ./mvnw package
[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------< com.sample.herokudemo:herokudemo >------------------
[INFO] Building herokudemo 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ herokudemo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 1 resource
[INFO] Copying 10 resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ herokudemo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 17 source files to /Users/tamurashingo/project/heroku-connect-demo/target/classes
[INFO] 
[INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ herokudemo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] skip non existing resourceDirectory /Users/tamurashingo/project/heroku-connect-demo/src/test/resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ herokudemo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/tamurashingo/project/heroku-connect-demo/target/test-classes
[INFO] 
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ herokudemo ---
[INFO] 
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------

...(省略)...

13:45:26.289 [main] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.4.3)

2021-08-14 13:45:26.555  INFO 13103 --- [           main] .s.h.h.HerokuconnectdemoApplicationTests : Starting HerokuconnectdemoApplicationTests using Java 1.8.0_302 on mac.local with PID 13103 (started by tamurashingo in /Users/tamurashingo/project/heroku-connect-demo)
2021-08-14 13:45:26.556  INFO 13103 --- [           main] .s.h.h.HerokuconnectdemoApplicationTests : The following profiles are active: local
2021-08-14 13:45:28.198  INFO 13103 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2021-08-14 13:45:29.116  INFO 13103 --- [           main] o.f.c.internal.license.VersionPrinter    : Flyway Community Edition 7.1.1 by Redgate
2021-08-14 13:45:29.255  INFO 13103 --- [           main] o.f.c.i.database.base.DatabaseType       : Database: jdbc:postgresql://localhost:5432/herokuconn (PostgreSQL 12.8)
2021-08-14 13:45:29.303  INFO 13103 --- [           main] o.f.core.internal.command.DbValidate     : Successfully validated 4 migrations (execution time 00:00.023s)
2021-08-14 13:45:29.317  INFO 13103 --- [           main] o.f.c.i.s.JdbcTableSchemaHistory         : Creating Schema History table "public"."flyway_schema_history" ...
2021-08-14 13:45:29.354  INFO 13103 --- [           main] o.f.core.internal.command.DbMigrate      : Current version of schema "public": << Empty Schema >>
2021-08-14 13:45:29.412  INFO 13103 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema "public" to version "1.20210813.153000 - create schema salesforce"
2021-08-14 13:45:29.437  INFO 13103 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema "public" to version "1.20210813.153200 - create product2"
2021-08-14 13:45:29.474  INFO 13103 --- [           main] o.f.core.internal.command.DbMigrate      : Successfully applied 4 migrations to schema "public" (execution time 00:00.128s)
2021-08-14 13:45:29.567  INFO 13103 --- [           main] .s.h.h.HerokuconnectdemoApplicationTests : Started HerokuconnectdemoApplicationTests in 3.272 seconds (JVM running for 4.011)
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.791 s - in com.github.tamurashingo.herokuconnectdemo.herokuconnectdemo.HerokuconnectdemoApplicationTests
2021-08-14 13:45:29.751  INFO 13103 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
[INFO] 
[INFO] Results:
[INFO] 
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] 
[INFO] 
[INFO] --- maven-jar-plugin:3.2.0:jar (default-jar) @ herokuconnectdemo ---
[INFO] Building jar: /Users/tamurashingo/project/heroku-connect-demo/target/herokuconnectdemo-0.0.1-SNAPSHOT.jar
[INFO] 
[INFO] --- spring-boot-maven-plugin:2.4.3:repackage (repackage) @ herokuconnectdemo ---
[INFO] Replacing main artifact with repackaged archive
[INFO] 
[INFO] --- maven-dependency-plugin:3.1.2:copy (copy-dependencies) @ herokuconnectdemo ---
[INFO] Configured Artifact: org.flywaydb:flyway-core:7.7.0:jar
[INFO] Configured Artifact: org.postgresql:postgresql:?:jar
[INFO] Copying flyway-core-7.7.0.jar to /Users/tamurashingo/project/heroku-connect-demo/target/dependency/flyway.jar
[INFO] Copying postgresql-42.2.18.jar to /Users/tamurashingo/project/heroku-connect-demo/target/dependency/postgres.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  12.110 s
[INFO] Finished at: 2021-08-14T13:45:33+09:00
[INFO] ------------------------------------------------------------------------

途中に出ているこのログがmigration時のログです。

2021-08-14 13:45:29.412  INFO 13103 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema "public" to version "1.20210813.153000 - create schema salesforce"
2021-08-14 13:45:29.437  INFO 13103 --- [           main] o.f.core.internal.command.DbMigrate      : Migrating schema "public" to version "1.20210813.153200 - create product2"

確認

SpringBootのアプリから確認するのはちょっと面倒なので、psqlでスキーマやテーブルが作成されているか確認します。

まずはスキーマの確認から。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
psql -U root -h 127.0.0.1 -W herokuconn
Password: 
psql (13.3, server 12.8 (Debian 12.8-1.pgdg100+1))
Type "help" for help.

herokuconn=# \dn
  List of schemas
    Name    | Owner 
------------+-------
 public     | root
 salesforce | root
(2 rows)

salesforceスキーマが作られています。

つづいてテーブルの確認。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
herokuconn=# \d salesforce.*
           Index "salesforce.hc_idx_product2_lastmodifieddate"
      Column      |            Type             | Key? |    Definition    
------------------+-----------------------------+------+------------------
 lastmodifieddate | timestamp without time zone | yes  | lastmodifieddate
btree, for table "salesforce.product2"

          Index "salesforce.hc_idx_product2_systemmodstamp"
     Column     |            Type             | Key? |   Definition   
----------------+-----------------------------+------+----------------
 systemmodstamp | timestamp without time zone | yes  | systemmodstamp
btree, for table "salesforce.product2"

          Index "salesforce.hcu_idx_product2_externalproductid__c"
        Column        |          Type          | Key? |      Definition      
----------------------+------------------------+------+----------------------
 externalproductid__c | character varying(255) | yes  | externalproductid__c
unique, btree, for table "salesforce.product2"

      Index "salesforce.hcu_idx_product2_sfid"
 Column |         Type          | Key? | Definition 
--------+-----------------------+------+------------
 sfid   | character varying(18) | yes  | sfid
unique, btree, for table "salesforce.product2"

                                                 Table "salesforce.product2"
        Column         |            Type             | Collation | Nullable |                     Default                     
-----------------------+-----------------------------+-----------+----------+-------------------------------------------------
 externalproductid__c  | character varying(255)      |           |          | 
 family                | character varying(255)      |           |          | 
 externalid            | character varying(255)      |           |          | 
 lastvieweddate        | timestamp without time zone |           |          | 
 stockkeepingunit      | character varying(180)      |           |          | 
 name                  | character varying(255)      |           |          | 
 externaldatasourceid  | character varying(18)       |           |          | 
 displayurl            | character varying(1000)     |           |          | 
 lastmodifieddate      | timestamp without time zone |           |          | 
 isdeleted             | boolean                     |           |          | 
 isactive              | boolean                     |           |          | 
 systemmodstamp        | timestamp without time zone |           |          | 
 lastmodifiedbyid      | character varying(18)       |           |          | 
 createddate           | timestamp without time zone |           |          | 
 quantityunitofmeasure | character varying(255)      |           |          | 
 createdbyid           | character varying(18)       |           |          | 
 productcode           | character varying(255)      |           |          | 
 description           | character varying(4000)     |           |          | 
 lastreferenceddate    | timestamp without time zone |           |          | 
 sfid                  | character varying(18)       | ucs_basic |          | 
 id                    | integer                     |           | not null | nextval('salesforce.product2_id_seq'::regclass)
 _hc_lastop            | character varying(32)       |           |          | 
 _hc_err               | text                        |           |          | 
Indexes:
    "product2_pkey" PRIMARY KEY, btree (id)
    "hc_idx_product2_lastmodifieddate" btree (lastmodifieddate)
    "hc_idx_product2_systemmodstamp" btree (systemmodstamp)
    "hcu_idx_product2_externalproductid__c" UNIQUE, btree (externalproductid__c)
    "hcu_idx_product2_sfid" UNIQUE, btree (sfid)

                Sequence "salesforce.product2_id_seq"
  Type   | Start | Minimum |  Maximum   | Increment | Cycles? | Cache 
---------+-------+---------+------------+-----------+---------+-------
 integer |     1 |       1 | 2147483647 |         1 | no      |     1
Owned by: salesforce.product2.id

   Index "salesforce.product2_pkey"
 Column |  Type   | Key? | Definition 
--------+---------+------+------------
 id     | integer | yes  | id
primary key, btree, for table "salesforce.product2"

こちらも問題なく作成できていました。

まとめ

Spring Boot + FlywayでHeroku Connectの環境を作る場合

  • salesforceスキーマはmigrationで作る
  • salesforceスキーマのテーブルもmigrationで作る
  • salesforceスキーマに関するmigrationファイルは標準の場所(db/migration)とは別の場所に配置する
    • 本番環境のmigrationは標準の場所(db/migration)のものだけ使うようにする