1. 概要

このチュートリアルでは、Hibernateタイプを見ていきます。 このライブラリは、コアHibernateORMにネイティブではないいくつかのタイプを提供します。

2. 依存関係

Hibernateタイプを有効にするには、適切なHibernateタイプの依存関係を追加するだけです。

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>2.9.7</version>
</dependency>

これは、Hibernateバージョン 5.4、5.3、、および5.2で動作します。

Hibernateのバージョンが古い場合、上記のArtifactIdの値は異なります。 バージョン5.1および5.0、の場合、 hibernate-types-51を使用できます。同様に、バージョン4.3にはhibernate-typesが必要です-43、およびバージョン 4.2、および4.1には、hibernate-types-4。が必要です。

このチュートリアルの例にはデータベースが必要です。 Dockerを使用して、データベースコンテナーを提供しました。 したがって、Dockerの作業コピーが必要になります。

したがって、データベースを実行および作成するには、以下を実行するだけで済みます。

$ ./create-database.sh

3. サポートされているデータベース

タイプは、Oracle、SQL Server、PostgreSQL、およびMySQLデータベースで使用できます。 したがって、Javaのタイプからデータベースの列タイプへのマッピングは、使用するデータベースによって異なります。 この例では、MySQLを使用して、JSONBinaryTypeをJSON列タイプにマップします。

サポートされているマッピングに関するドキュメントは、HibernateTypesリポジトリにあります。

4. データ・モデル

このチュートリアルのデータモデルを使用すると、アルバムや曲に関する情報を保存できます。 アルバムにはカバーアートと1つ以上の曲が含まれています。 曲にはアーティストと長さがあります。 カバーアートには、2つの画像URLとUPCコードがあります。 最後に、アーティストには名前、国、音楽のジャンルがあります。

以前は、モデル内のすべてのデータを表すテーブルを作成していました。 しかし、利用可能な型ができたので、代わりにデータの一部をJSONとして非常に簡単に保存できます。

このチュートリアルでは、アルバムと曲のテーブルのみを作成します。

public class Album extends BaseEntity {
    @Type(type = "json")
    @Column(columnDefinition = "json")
    private CoverArt coverArt;

    @OneToMany(fetch = FetchType.EAGER)
    private List<Song> songs;

   // other class members
}
public class Song extends BaseEntity {

    private Long length = 0L;

    @Type(type = "json")
    @Column(columnDefinition = "json")
    private Artist artist;

    // other class members
}

JsonStringType を使用して、カバーアートとアーティストをこれらのテーブルのJSON列として表します。

public class Artist implements Serializable {
 
    private String name;
    private String country;
    private String genre;

    // other class members
}
public class CoverArt implements Serializable {

    private String frontCoverArtUrl;
    private String backCoverArtUrl;
    private String upcCode;

    // other class members
}

ArtistクラスとCoverArtクラスはPOJOであり、エンティティではないことに注意してください。さらに、これらは @Type(type =“ json”)[X200Xで定義されたデータベースエンティティクラスのメンバーです。 ]注釈。

4.1. JSONタイプの保存

データベースがJSONとして保存するメンバーを含むようにアルバムと曲のモデルを定義しました。 これは、提供されているjsonタイプを使用しているためです。 その型を使用できるようにするには、型定義を使用してその型を定義する必要があります。

@TypeDefs({
  @TypeDef(name = "json", typeClass = JsonStringType.class),
  @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class BaseEntity {
  // class members
}

JsonStringTypeおよびJsonBinaryType@Typeにより、タイプjsonおよびjsonbが使用可能になります。

最新のMySQLバージョンは、列タイプとしてJSONをサポートしています。 したがって、 JDBCは、これらのタイプのいずれかを文字列として列から読み取ったJSONまたは列に保存されたオブジェクトを処理します。これは、列に正しくマップするには、JsonStringTypeを使用する必要があることを意味します。タイプ定義。

4.2. Hibernate

最終的に、私たちのタイプは、JDBCとHibernateを使用してSQLに自動的に変換されます。 これで、いくつかの曲オブジェクト、アルバムオブジェクトを作成し、それらをデータベースに永続化できます。  続いて、Hibernateは次のSQLステートメントを生成します。

insert into song (name, artist, length, id) values ('A Happy Song', '{"name":"Superstar","country":"England","genre":"Pop"}', 240, 3);
insert into song (name, artist, length, id) values ('A Sad Song', '{"name":"Superstar","country":"England","genre":"Pop"}', 120, 4);
insert into song (name, artist, length, id) values ('A New Song', '{"name":"Newcomer","country":"Jamaica","genre":"Reggae"}', 300, 6)
insert into album (name, cover_art, id) values ('Album 0', '{"frontCoverArtUrl":"http://fakeurl-0","backCoverArtUrl":"http://fakeurl-1","upcCode":"b2b9b193-ee04-4cdc-be8f-3a276769ab5b"}', 7)

予想どおり、 json タイプのJavaオブジェクトはすべてHibernateによって変換され、整形式のJSONとしてデータベースに保存されます。

5. 一般的なタイプの保存

このライブラリは、JSONベースの列をサポートするだけでなく、java.timeYearMonth Year、Monthなどのジェネリック型も追加します。パッケージ。

これで、HibernateまたはJPAでネイティブにサポートされていないこれらのタイプをマップできます。 また、これらを Integer String、、またはDate列として格納できるようになりました。

たとえば、曲の録音日を song モデルに追加し、それをIntegerとしてデータベースに保存するとします。 Songエンティティクラス定義でYearMonthIntegerTypeを使用できます。

@TypeDef(
  typeClass = YearMonthIntegerType.class,
  defaultForType = YearMonth.class
)
public class Song extends BaseEntity {
    @Column(
      name = "recorded_on",
      columnDefinition = "mediumint"
    )
    private YearMonth recordedOn = YearMonth.now();

    // other class members  
}

recordsedOn プロパティ値は、提供したtypeClassに変換されます。 その結果、事前定義されたコンバーターは、データベース内の値をIntegerとして保持します。

6. その他のユーティリティクラス

Hibernateタイプには、Hibernateを使用する際の開発者エクスペリエンスをさらに向上させるいくつかのヘルパークラスがあります。

CamelCaseToSnakeCaseNamingStrategy は、Javaクラスのキャメルケースのプロパティをデータベースのスネークケースの列にマップします。

ClassImportIntegrator を使用すると、JPAコンストラクターパラメーターで単純なJavaDTOクラス名の値を使用できます。

ListResultTransformerクラスとMapResultTransformerクラスもあり、JPAで使用される結果オブジェクトのよりクリーンな実装を提供します。 さらに、ラムダの使用をサポートし、古いJPAバージョンとの下位互換性を提供します。

7. 結論

このチュートリアルでは、HibernateタイプのJavaライブラリと、それがHibernateとJPAに追加する新しいタイプを紹介しました。 また、ライブラリによって提供されるユーティリティと汎用タイプのいくつかについても調べました。

例とコードスニペットの実装は、GitHubから入手できます。