Posted at

H2 をデータベースに指定した場合、spring.jpa.hibernate.ddl-auto を create にしてもテーブルが作成されない現象

More than 1 year has passed since last update.


概要

Spring Boot にて AuditorAware の機能を使用して作成日、更新日を設定していましたが、通常の SQL 実行時においてもデフォルト値として現在日時を設定するために columnDefinition にて既定値を設定するよう設定した結果、H2 データベースにテーブルが作成されなくなる現象が発生しました。

なお、MYSQL をデータベースに指定した場合、正常にテーブルが作成される動作になりました。


Audit.java

@MappedSuperclass

@EntityListeners(AuditingEntityListener.class)
@Getter
public class Audit implements Serializable {
@CreatedBy
private String createdBy;

@CreatedDate
@Column(nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
private LocalDateTime createdDate;

@LastModifiedBy
private String modifiedBy;

@LastModifiedDate
@Column(nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP")
private LocalDateTime modifiedDate;
}



原因と解決策

どうやら、2017/10/20 現在の H2 データベースの動作においては、ON UPDATE が指定できないようです。

columnDefinition を変更した結果、正常に動作するようになりました。

update については、@EnableJpaAuditing にて自動的に更新日時が設定され、通常の SQL にて UPDATE を打つ可能性は低いですが、どこで更新が行われているかわからなくなるかもしれないと考え指定しました。

テストを H2 データベースにて正常に行う方が、更新日時の更新のタイミングを追いかける必然性より高いと判断したので、下記のように変更しました。


Audit.java

@MappedSuperclass

@EntityListeners(AuditingEntityListener.class)
@Getter
public class Audit implements Serializable {
@CreatedBy
private String createdBy;

@CreatedDate
@Column(nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
private LocalDateTime createdDate;

@LastModifiedBy
private String modifiedBy;

@LastModifiedDate
@Column(nullable = false, columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
private LocalDateTime modifiedDate;
}



補足

上記のエンティティを継承したクラスは、テスト時においては、下記 AuditorAware が動作いたしますので、CreatedBy, LastModifiedBy については、TEST_AUDITOR が設定されます。


MockAuditAware.java

@Component

public class MockAuditorAware implements AuditorAware<String> {

private String auditor;

public static final String TEST_AUDITOR = "TEST_AUDITOR";

@Override
public String getCurrentAuditor() { return TEST_AUDITOR; }

public void setCurrentAuditor(String auditor) {
this.auditor = auditor;
}

}


MockAuditAware クラスについては、テスト用の Configuration クラスに、@EnableJpaAuditing(auditorAwareRef = "mockAuditorAware") を設定してテスト時に起動するよう設定しております。


TestConfig.java

@Profile("test")

@TestConfiguration
@ComponentScan(basePackageClasses = {TestRoot.class})
@Configuration
@TestPropertySource("classpath:application-test.properties")
@EnableJpaAuditing(auditorAwareRef = "mockAuditorAware")
public class TestConfig {
}