web-dev-qa-db-ja.com

H2は私のSpring Bootアプリでテーブルを作成/更新しません。エンティティに何か問題がありますか?

Hibernateを使用してCRUDリポジトリを作成し、H2データベースにいくつかのデータを保持したいと思います。

エントリを保存するデータベースを取得できません。現在、サンプルエントリを作成して、dbの更新中にそれを実現しようとしています。エントリはログで良好に見えますが、テーブルは作成/更新/生成されません。

この場合、Hibernateがテーブルを作成できないのはなぜですか?(問題がデータの構造にある場合)

これが私のエンティティ、Game.Javaクラスです(@Columnアノテーションなしで試しましたが、違いはありません。IDは自動生成されません。毎回自分のIDを入力できます):

@Entity
@Table(name = "GAME")
public class Game {

    @Id
    @Column (name = "ID")
    private long id;

    @Column (name = "NAME")
    private String name;

    @Column(name = "STORYLINE", length = 4000)
    private String storyline;

    @Column(name = "AGGREGATED_RATING")
    @JsonProperty("aggregated_rating")
    private double aggregatedRating;

    @Column(name = "FIRST_RELEASE_DATE")
    @JsonProperty("first_release_date")
    private long firstReleaseDate;

    @Embedded
    private Cover cover;

    public Game(){

    }

    public Game(long id, String name, String storyline, double aggregatedRating, long firstReleaseDate, Cover cover) {
        this.id = id;
        this.name = name;
        this.storyline = storyline;
        this.aggregatedRating = aggregatedRating;
        this.firstReleaseDate = firstReleaseDate;
        this.cover = cover;
    }

    public long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getStoryline() {
        return storyline;
    }

    public double getAggregatedRating() {
        return aggregatedRating;
    }

    public long getFirstReleaseDate() {
        return firstReleaseDate;
    }

    public Cover getCover() {
        return cover;
    }


}

そして、ここにCover.Javaクラスがあります:

@Embeddable
public class Cover {

    @Column (name = "URL")
    private String url;
    @JsonProperty("cloudinary_id")
    @Column (name = "CLOUDINARY_ID")
    private String cloudinaryId;
    @Column (name = "WIDTH")
    private Integer width;
    @Column (name = "HEIGHT")
    private Integer height;

    public Cover(){
    }

    public Cover(String url, String cloudinaryId, Integer width, Integer height) {
        this.url = url;
        this.cloudinaryId = cloudinaryId;
        this.width = width;
        this.height = height;
}

    public String getUrl() {
        return url;
    }

    public String getCloudinaryId() {
        return cloudinaryId;
    }

    public Integer getWidth() {
        return width;
    }

    public Integer getHeight() {
        return height;
    }

}

ここで、application.propertiesファイルでH2データベースを構成しました。

spring.h2.console.enabled=true
spring.h2.console.path=/h2_console
spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.jpa.hibernate.ddl-auto = update
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

Repositoryは次のように構成されます:

import org.springframework.data.repository.CrudRepository;

import Java.util.List;

public interface GameRepository extends CrudRepository<Game, Long> {
    List<Game> findAllByName(String name);
}

Localhost:8080/testに移動してリポジトリをテストします。サンプルエントリをテーブルに挿入する必要があります。

@RequestMapping("/test")
public String saveSth(){
    gameRepository.save(new Game(127, "Assassin's Creed II", "The lineage continues as this new chapter introduces Ezio, inheritor of the talents and creed of the Assassins. His family murdered by rival families, Ezio resolves to learn the ancient art of the Assassin in order to seek revenge. He will not do so alone though, allying with historical figures such as philosopher and writer Niccolò Machiavelli. You will also be able to master the art of the assassin with all new weapons and instruments created by the renowned inventor and genius of the Renaissance, Leonardo Da Vinci himself.", 90.25, 1258416000000L, new Cover("//images.igdb.com/igdb/image/upload/t_thumb/doczeiofd1ckpapdhqs7.jpg", "doczeiofd1ckpapdhqs7", 1000, 1426)));
    return "success";
}

次のログを取得します。

2017-07-25 13:09:58.873 DEBUG 9442 --- [nio-8080-exec-1] org.hibernate.SQL                        : select game0_.id as id1_0_0_, game0_.aggregated_rating as aggregat2_0_0_, game0_.cloudinary_id as cloudina3_0_0_, game0_.height as height4_0_0_, game0_.url as url5_0_0_, game0_.width as width6_0_0_, game0_.first_release_date as first_re7_0_0_, game0_.name as name8_0_0_, game0_.storyline as storylin9_0_0_ from game game0_ where game0_.id=?
Hibernate: select game0_.id as id1_0_0_, game0_.aggregated_rating as aggregat2_0_0_, game0_.cloudinary_id as cloudina3_0_0_, game0_.height as height4_0_0_, game0_.url as url5_0_0_, game0_.width as width6_0_0_, game0_.first_release_date as first_re7_0_0_, game0_.name as name8_0_0_, game0_.storyline as storylin9_0_0_ from game game0_ where game0_.id=?
2017-07-25 13:09:58.875 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [BIGINT] - [127]
2017-07-25 13:09:58.894 DEBUG 9442 --- [nio-8080-exec-1] org.hibernate.SQL                        : insert into game (aggregated_rating, cloudinary_id, height, url, width, first_release_date, name, storyline, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: insert into game (aggregated_rating, cloudinary_id, height, url, width, first_release_date, name, storyline, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?)
2017-07-25 13:09:58.895 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [DOUBLE] - [90.25]
2017-07-25 13:09:58.896 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [2] as [VARCHAR] - [doczeiofd1ckpapdhqs7]
2017-07-25 13:09:58.896 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [3] as [INTEGER] - [1426]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [4] as [VARCHAR] - [//images.igdb.com/igdb/image/upload/t_thumb/doczeiofd1ckpapdhqs7.jpg]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [5] as [INTEGER] - [1000]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [6] as [BIGINT] - [1258416000000]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [7] as [VARCHAR] - [Assassin's Creed II]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [8] as [VARCHAR] - [The lineage continues as this new chapter introduces Ezio, inheritor of the talents and creed of the Assassins. His family murdered by rival families, Ezio resolves to learn the ancient art of the Assassin in order to seek revenge. He will not do so alone though, allying with historical figures such as philosopher and writer Niccolò Machiavelli. You will also be able to master the art of the assassin with all new weapons and instruments created by the renowned inventor and genius of the Renaissance, Leonardo Da Vinci himself.]
2017-07-25 13:09:58.897 TRACE 9442 --- [nio-8080-exec-1] o.h.type.descriptor.sql.BasicBinder      : binding parameter [9] as [BIGINT] - [127]

データはパラメーターにバインドされているように見えますが、H2コンソールではSELECT * FROM GAMEが返されます:SELECT * FROM GAME;テーブル「GAME」が見つかりません。 SQLステートメント:SELECT * FROM GAME [42102-193] 42S02/42102(ヘルプ)

Create-dropやcreateなどの他のH2モードを試しましたが、成功しませんでした。私が心配しているのは、正しい行を持つ空のテーブルをデータベースに作成させて、エントリの準備ができないことです。

エンティティに何か問題があるか、GameRepositoryの設定にないのではないかと思いますが、このエラーを修正するアイデアはこれ以上ありません。

ここにあるものを達成したい: http://javasampleapproach.com/spring-framework/spring-boot/integrate-h2-database-springboot-spring-jpa-embedded-mode そしてここに:- http://www.simplecodestuffs.com/value-object-entity-object-in-hibernate-mapping/

また、変更のためにこのチュートリアルセットを試しました: https://springframework.guru/using-the-h2-database-console-in-spring-boot-with-spring-security/ = https://springframework.guru/spring-boot-web-application-part-3-spring-data-jpa/

しかし、これまでのところ運はありません。

8
VapeKop

データはパラメーターにバインドされているように見えますが、H2コンソールではSELECT * FROM GAMEから何も返されません。テーブルが存在しません。

H2のin-memoryインスタンスを使用しています:

spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

このモードでは、in-memoryデータベースを起動した別のクライアントからの変更内容を表示できません。
他のクライアントからの変更を確認するには、TCPモードを使用する必要があります。

次の2つのソリューションがあります。

  • ファイルを使用してH2のインスタンスを永続化します。

データベースファイルはどこに保存されていますか?

Jdbc:h2:〜/ testのようなデータベースURLを使用する場合、データベースはユーザーディレクトリに保存されます。 Windowsの場合、これは通常C:\ Documents and Settings \またはC:\ Users \です。ベースディレクトリが設定されていない場合(jdbc:h2:./ testのように)、データベースファイルはアプリケーションが起動されたディレクトリ(現在の作業ディレクトリ)に格納されます。スタートメニューからH2コンソールアプリケーションを使用する場合、これは/ binです。ベースディレクトリは、データベースURLで設定できます。固定パスまたは相対パスを使用できます。 URL jdbc:h2:file:./ data/sampleを使用する場合、データベースは(現在の作業ディレクトリに関連する)ディレクトリデータに格納されます。まだ存在しない場合、ディレクトリは自動的に作成されます。完全修飾ディレクトリ名(およびWindowsの場合はドライブ名)を使用することもできます。例:jdbc:h2:file:C:/ data/test

  • インメモリインスタンスを使用し続けますが、TCPモードを使用します。

交換:

spring.datasource.url=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1

によって:

spring.datasource.url=jdbc:h2:tcp://localhost/~/test

一般的に、データベースに挿入されたものを本当に知りたい場合、JPAエンティティユニットテスト中にこのモードに切り替えます。

公式ドキュメント から:

インメモリーデータベース

特定のユースケース(例:ラピッドプロトタイピング、テスト、高パフォーマンス操作、読み取り専用データベース)の場合、データの永続化やデータの変更の永続化は必要ない場合があります。このデータベースは、データが永続化されないインメモリモードをサポートしています。 ...

場合によっては、メモリ内データベースへの接続が1つだけ必要です。これは、開かれるデータベースがプライベートであることを意味します。この場合、データベースURLはjdbc:h2:memです。同じ仮想マシン内で2つの接続を開くことは、2つの異なる(プライベート)データベースを開くことを意味します。

同じメモリ内データベースへの複数の接続が必要になる場合があります。この場合、データベースURLには名前を含める必要があります。例:jdbc:h2:mem:db1。このURLを使用した同じデータベースへのアクセスは、同じ仮想マシンとクラスローダー環境内でのみ機能します。

別のプロセスまたは別のコンピューターからインメモリデータベースにアクセスするには、インメモリデータベースと同じプロセスでTCPサーバーを起動する必要がありますその後、他のプロセスは、jdbc:h2:tcp:// localhost/mem:db1。などのデータベースURLを使用して、TCP/IPまたはTLSを介してデータベースにアクセスする必要があります。


代替のスタンドアロンH2コンソール:Spring Bootアプリケーションからアクセス可能なH2コンソールを使用する

実際、H2データベースは、ブラウザベースのコンソールを提供します Spring Bootはあなたのために自動設定できます 。これらの条件が満たされると、コンソールは自動構成されます。

  • サーブレットベースのWebアプリケーションを開発しています。
  • com.h2database:h2はクラスパス上にあります。
  • Spring Bootの開発者ツールを使用しています。

したがって、devでのみアクセス可能になります。一般的にあなたが望むもの。

デフォルトでは、コンソールは/h2-consoleで利用可能です。
spring.h2.console.pathプロパティを設定して変更します。

12
davidxxx

たとえば、H2コンソールに移動します。 http:// localhost:9090/h2-console / およびJDBC URLフィールドに、jdbc:h2と入力します。 mem:testdbは、RAM内のtestdbデータベースへの接続を構成します。

17
Dev M

メインクラス(Springブートアプリケーションクラス)が定義されたエンティティをスキャンできるかどうかを確認します。これは通常、エンティティがメインクラスとは異なるパッケージにある場合に発生します。

3
Ashlin Karkada