永続性モデル

永続表およびSpring Data Framework注釈のスキーマについて学習します。

エンティティは、軽量の永続性ドメイン・オブジェクトです。エンティティの永続性状態は、Java Beans/Plain Old Java Object (POJO)を使用する永続フィールドによって表されます。

Spring Data Frameworkは、Oracle NoSQL Database表に向けたエンティティの永続性をサポートします。エンティティは表にマップされます。そのエンティティのIDフィールドが、その表の主キー列にマップされます。その他のエンティティ内のすべてのフィールドは、その表のJSON列にマップされます。エンティティの各インスタンスは、その表の単一行として格納されます。そのインスタンスのIDフィールドの値は、その行の主キー値として格納されます。そのインスタンスのその他すべてのフィールド(その他のオブジェクトを含む) (「JSON列」を参照)の値は、シリアライズされて、その行のJSON列に値として格納されます。実質的に、表には常に主キー列とJSON列の2つの列のみが含まれます。

永続性POJOに、別の表にマップされる別の永続性POJO (ネストされたオブジェクト)への参照がある場合、Spring Data Frameworkではオブジェクトを複数の表にシリアライズしません。かわりに、すべてのネストされたオブジェクトがシリアライズされて、値としてJSON列に格納されます。JSON列のマッピングの詳細は、「JSON列」を参照してください。

次に、@NosqlTableおよび@NosqlIdの注釈が付いたエンティティの構文を示します。次の例では、@NosqlTable注釈が付いたStudentクラスが、Oracle NoSQL DatabaseStudentという名前の表にマップされます。@NosqlId注釈が付いたIDフィールドは、Student表の主キー・フィールドになります。firstNameフィールドとlastNameフィールドは、Student表のkv_json_という名前の単一のJSONフィールドにマップされます。

リポジトリからエントリを取得するときには、ドライバはエンティティ・クラスをインスタンス化する必要があります。これらのクラスには、デフォルト・コンストラクタ、またはpublicかpackage protectedの空のコンストラクタが必要です。

ノート:

このクラスには他のコンストラクタもある場合があります。
/*The @NosqlTable annotation specifies that 
this class will be mapped to an Oracle NoSQL Database table.*/
@NosqlTable
public class Student {
    //The @NosqlId annotation specifies that this field will act as the ID field.
    @NosqlId
    public long ID;
  
    public String firstName;
    public String lastName;
  
    public Student() {}
}

表名

デフォルトでは、エンティティ・クラス名が表名として使用されます。@NosqlTable注釈を使用することで、別の表名を指定できます。@NosqlTable注釈を使用すると、表名やタイムアウトなどの追加の構成パラメータを定義できます。

たとえば、Studentという名前のエンティティは、Studentという名前の表に永続化されます。Studentという名前のエンティティをLearnerという名前の表に永続化する場合は、@NosqlTable注釈を使用します。

@NosqlTable注釈を指定すると、次の構成を指定できるようになります。

表1-1 NosqlTable注釈の属性

パラメータ Oracle NoSQL Databaseでは無視/オプション/必須 Oracle NoSQL Database Cloud Serviceでは無視/オプション/必須 デフォルト 説明
tableName String オプション オプション

表の名前(単純または名前空間で修飾された形式)を指定します。

空の場合は、エンティティ・クラス名が使用されます。

ネームスペースの詳細は、『SQLリファレンス・ガイド』ネームスペースの管理を参照してください。

Oracle NoSQL Database Cloud Serviceでは、ネームスペース部分(指定されている場合)がコンパートメント名として使用されます。コンパートメントの使用の詳細は、Oracle NoSQL Database Cloud Serviceガイドのコンパートメントの作成を参照してください。

autoCreateTable boolean オプション オプション true

表が存在しない場合に作成する必要があるかどうかを指定します。

ノート:

Spring Data Frameworkは、initフェーズでアプリケーションで使用されるリポジトリを検索します。表が存在しないときに、@NosqlTable注釈のautoCreateTabletrueの場合は、initフェーズで表が作成されます。
readUnits int 無視 必須 -1

表を作成する場合に使用する最大読取りスループットを指定します。

readUnitsの詳細は、Oracle NoSQL Database Cloud Serviceサービスの計画を参照してください。

ノート:

Oracle NoSQL Database Cloud Serviceでは、readUnitsパラメータを0より大きい値に設定する必要があります。値を設定しない場合、Oracle NoSQL Database Cloud Serviceによってエラーが返されます。
writeUnits int 無視 必須 -1

表を作成する場合に使用する最大書込みスループットを指定します。

writeUnitsの詳細は、Oracle NoSQL Database Cloud Serviceサービスの計画を参照してください。

ノート:

Oracle NoSQL Database Cloud Serviceでは、writeUnitsパラメータを0より大きい値に設定する必要があります。値を設定しない場合、Oracle NoSQL Database Cloud Serviceによってエラーが返されます。
storageGB int 無視 必須 -1

表を作成する場合に、表に許可される記憶域の最大量をGB単位で指定します。

storageGBの詳細は、Oracle NoSQL Database Cloud Serviceサービスの計画を参照してください。

ノート:

Oracle NoSQL Database Cloud Serviceでは、storageGBパラメータを0より大きい値に設定する必要があります。値を設定しない場合、Oracle NoSQL Database Cloud Serviceによってエラーが返されます。
timeout int オプション オプション 0

タイムアウト例外がスローされるまでに操作に許可される時間の最長時間(ミリ秒)を指定します。

timeoutの値が設定されていない場合は、NoSQLHandleConfigクラスで設定されているタイムアウトが使用されます。 getTableRequestTimeout()メソッドを使用してNoSQLHandleConfigクラスからタイムアウトを取得する方法の詳細は、Java SDK APIリファレンスNoSQLHandleConfigを参照してください。

timeout値は、NosqlRepository.setTimeout(int)メソッドを使用して変更することもできます。詳細は、SDK for Spring Data APIリファレンスsetTimeoutに関する項を参照してください。

consistency String オプション オプション EVENTUAL

読取り操作に使用する整合性を指定します。

有効な値は、EVENTUALおよびABSOLUTEです。oracle.nosql.driver.Consistencyに基づきます。Java SDK APIリファレンス整合性に関する項を参照してください。

ノート:

これは、すべての読取り操作に対するデフォルトです。これは、NosqlRepository.setConsistency(String)を使用するとオーバーライドできます。詳細は、SDK for Spring Data APIリファレンスsetConsistencyに関する項を参照してください。
durability String オプション オプション COMMIT_NO_SYNC

この表に適用されるすべての書込み操作のデフォルトの永続性を設定します。

oracle.nosql.driver.Durabilityに基づく有効な値は、COMMIT_NO_SYNC, COMMIT_SYNCおよびCOMMIT_WRITE_NO_SYNCです。Java SDK APIリファレンス永続性を参照してください。

capacityMode NosqlCapacityMode

詳細は、NosqlCapacityModeを参照してください。

オプション オプション NosqlCapacityMode.PROVISIONED

表の作成時に容量モードを設定します。これは、クラウドまたはクラウドのシミュレーション・シナリオでのみ適用されます。

表は、Provisioned CapacityまたはOn-Demand Capacityを使用して作成されます。詳細は、Oracle NoSQL Database Cloud Serviceクラウドの概念を参照してください。

TableLimitsインスタンスの値を、容量モードに基づいて次のように設定します。
  • capacityModeを「PROVISIONED」に設定し、3つのTableLimits: readUnits, writeUnitsおよびstorageGBのすべてを0より大きい値に設定します。
  • capacityModeを「ON_DEMAND」に設定し、storageGBを0より大きい値に設定します。
ttl int オプション オプション 0

表の作成時にデフォルトの表レベルTime to Live (TTL)を設定します。TTLを使用すると、指定した期間の経過後に表の行を自動的に期限切れにできます。

値が設定されていない場合、値Constants.NOTSET_TABLE_TTLが使用されます。つまり、表レベルのTTLは適用されません。『SDK for Spring Data APIリファレンス』NOTSET_TABLE_TTLを参照してください。

このパラメータは、autoCreateTableがtrueに設定されている場合にのみ適用可能です。

ttlUnit TtlUnit オプション オプション NosqlTable.TtlUnit.DAYS

TTL値の単位を設定します。有効な値は、NosqlTable.TtlUnit.DAYSおよびNosqlTable.TtlUnit.HOURSです。

値が設定されていない場合、デフォルト値の日が使用されます。

このパラメータは、autoCreateTableがtrueに設定されている場合にのみ適用可能です。

主キー

表には主キーが必要です。エンティティのIDという名前のフィールドが主キーとして使用されます。@NosqlId注釈または@id注釈を使用すると、主キーとして指定するエンティティ内の別のフィールド(ID以外の名前のフィールド)を選択できます。

IDフィールドが主キー列にマップされると、Spring Data Frameworkは、そのフィールドに対応するデータ型を表に格納する前に自動的に割り当てます。次に、IDフィールドについて、JavaとOracle NoSQL Databaseのデータ型間のマッピングのリストを示します。

次の表に示すJavaの型のみが、主キーに使用できる有効なデータ型です。

表1-2 JavaとOracle NoSQL Databaseの型のマッピング

Javaの型 Oracle NoSQL Databaseの型

java.lang.String

STRING

int

java.lang.Integer

INTEGER

long

java.lang.Long

LONG

double

java.lang.Double

float

java.lang.Float

DOUBLE

ノート:

doublejava.lang.Doublefloatおよびjava.lang.Floatは主キーにできますが、有効なgenerated=trueの型ではありません

ノート:

Oracle NoSQL DatabaseFLOAT型はNoSQL SDK for Javaでは明示的に使用されていないため、Javaのfloatjava.lang.FloatDOUBLE型にマップされます。

java.math.BigDecimal

java.math.BigInteger

NUMBER

boolean

java.lang.Boolean

BOOLEAN

java.util.Date

java.sql.Timestamp

java.time.Instant

TIMESTAMP (P)

Spring Data Frameworkは、次のルールを使用して主キーを推定します。
  • @NosqlId注釈: 主キーとして有効なデータ型のフィールドに@NosqlId注釈が使用されている場合は、そのフィールドが主キーとみなされます。主キーとして有効なデータ型以外の型のフィールドに@NosqlIdを使用すると、エラーが発生します。詳細は、SDK for Spring Data APIリファレンスNosqlIdに関する項を参照してください。
  • @org.springframework.data.annotation.Id注釈: 主キーとして有効なデータ型のフィールドに@org.springframework.data.annotation.Idフィールド注釈が使用されている場合は、そのフィールドが主キーとみなされます。主キーとして有効なデータ型以外の型のフィールドに@org.springframework.data.annotation.Idを使用すると、エラーが発生します。
  • 未指定: 前述の2つの注釈のどちらも指定されていない場合、Spring Data Frameworkは、主キーとしてIDという名前のフィールドを使用します。
次の場合は、エラーが発生します。
  • エンティティに@NosqlId注釈、@org.springframework.data.annotation.Id注釈またはIDフィールドが見つからない場合。主キー・フィールドを推測できません。
  • エンティティに@NosqlIdまたは@org.springframework.data.annotation.Idの注釈付きフィールドが複数使用されている場合。複数の主キー・フィールドが推測されます。

ノート:

@NosqlId注釈または@org.springframework.data.annotation.Id注釈を付けるフィールドの名前は、kv_json_という名前にしないでください。これは、Spring Data Frameworkによって作成される表のデータ列にkv_json_という名前が付けられ、永続エンティティの主キーの属性としてリストされていないすべての属性を格納するJSON列になるためです。

@NosqlIdフィールド注釈は、次の追加構成を受け入れます。

表1-3 NosqlId注釈の属性

パラメータ オプション/必須 デフォルト 説明
generated boolean オプション false

IDが自動生成されるかどうかを指定します。

  • trueの場合は、プログラムによって自動生成されるものとして定義されます。
    • int/Integerlong/LongBigIntegerまたはBigDecimalの場合は、GENERATED ALWAYS as IDENTITYが使用されます。
    • Stringの場合は、String as UUID GENERATED BY DEFAULTが使用されます。
  • falseの場合は、アプリケーションで値を管理する必要があります。

ノート:

コンポジット・キーは自動生成できません。@NosqlId.autoGenerated=trueを設定すると、エラーが発生します。コンポジット・キーを使用する場合は、すべての読取り/書込みコールのキー値を管理する必要があります。キー値が設定されていない場合、Oracle NoSQL Databaseはエラーを生成します。

コンポジット主キー

コンポジット主キーには、複数の主キー・フィールドが含まれます。コンポジット・キーを表すためにコンポジット・キー・クラス・タイプを定義できます。

コンポジット・キー・クラスは、エンティティ・クラスの複数の主キー・フィールドにマップされるタイプです。コンポジット・キー・クラスはシリアライズ可能である必要があり、equalsおよびhashcodeメソッドを定義する必要があります。このクラスは、プリミティブ・データ型のフィールドで構成されている必要があります。

ノート:

コンポジット・キー・クラスのユーザー定義メソッドの等価性チェックは、Oracle NoSQL Databaseでデータベース・タイプとマップされたキーとの間で実行される等価性チェックと一致している必要があります。

@NosqlKey注釈を使用すると、コンポジット・キー・クラスのコンポジット主キーのコンポーネントを指定できます。

表1-4 Nosqlkey注釈の属性

パラメータ オプション/必須 デフォルト 説明
shardKey boolean オプション true

主キー・フィールドがシャード・キーでもあるかどうかを識別します。シャード・キーは、シャード間の行の分散に影響します。

  • trueの場合、Spring Data Frameworkは主キー・フィールドをシャード・キーの一部とみなします。
  • falseの場合、主キー・フィールドはシャード・キーの一部ではありません。

Nosqlkey注釈にshardKeyパラメータを指定しない場合、Spring Data Frameworkは主キー・フィールドをシャード・キーとして作成します。

order int オプション システム決定

コンポジット・キー・クラスの主キー内のシャード・キーおよび非シャード・キーの順序を指定します。

次のルールに基づいてorder値を設定できます。設定しない場合、Spring Data Frameworkはエラーを生成します。

  • シャード・キーの順序は、非シャード主キー・フィールドの順序より小さくする必要があります。
  • 順序は、すべての主キー・フィールドに指定するか、まったく指定しない必要があります。Spring Data Frameworkは、主キー・フィールドの部分リストに対する順序の指定をサポートしていません。
  • 各主キー・フィールドのorder値は一意である必要があります。

Nosqlkey注釈にorderパラメータを指定しない場合、Spring Data Frameworkでは、フィールド名のアルファベット順にシャード・キーおよび非シャード・キーが個別に順序付けされます。「コンポジット・キーの順序付け」の例を参照してください。

@NosqlKey注釈の詳細は、SDK for Spring Data APIリファレンス・ドキュメントのNosqlKeyを参照してください。

例: コンポジット・キーの順序付け

主キー・フィールドuniversityIdacademicYearおよびstudentIdがコンポジット・キー・クラスに定義されているとします。

universityIdおよびacademicYearフィールドは、シャード・キーの一部として定義できます。これらのシャード・キーの順序値は、非シャード・キーであるstudentIdフィールドより小さくする必要があります。次のサンプル・コードを使用してコンポジット・クラスを作成できます。
/* Define a composite Key class */

public class StudentKey implements Serializable {
    
    @NosqlKey(shardKey = true, order = 1)
    long universityId;

    @NosqlKey(shardKey = true, order = 0)
    int academicYear;

    @NosqlKey(shardKey = false, order = 2)
    long studentId;

    /* public or package protected constructor required when retrieving from database */
    public StudentKey() {
    }
}

前述の例では、academicYearフィールドは、表の作成時に最初の主キー・フィールドとみなされます。

Spring Data Frameworkは、次のDDLを使用して表を作成します。
/* Table DDL */

CREATE TABLE IF NOT EXISTS Students (
   academicYear INTEGER,
   universityId LONG,
   studentId LONG,
   kv_json_ JSON,
   PRIMARY KEY(SHARD(academicYear, universityId), studentId)
)
orderフィールドを指定しないコンポジット・キー・クラスを考えてみます。
/* Define a composite Key class */

public class StudentKey implements Serializable {
    
    @NosqlKey(shardKey = true)
    long universityId;

    @NosqlKey(shardKey = true)
    int academicYear;

    @NosqlKey(shardKey = false)
    long studentId;

    @NosqlKey(shardKey = false)
    long branchId;

    /* public or package protected constructor required when retrieving from database */
    public StudentKey() {
    }
}
前述の例では、Spring Data Frameworkによって、主キー内のフィールド名のアルファベット順でシャード・キーおよび非シャード・キーが作成されます。表のDDLは次のとおりです。
/* Table DDL */

CREATE TABLE IF NOT EXISTS Students (
   academicYear INTEGER,
   universityId LONG,
   branchId LONG,
   studentId LONG,
   kv_json_ JSON,
   PRIMARY KEY(SHARD(academicYear, universityId), branchId, studentId)
)

次の場合、Spring Data Frameworkでは、すべての主キー・フィールドがシャード・キーとみなされ、アルファベット順が使用されます。

  • @NosqlKey注釈を使用せずにコンポジット・キー・クラスの主キー・フィールドを宣言した場合。
  • @NosqlKey注釈でshardKeyおよびorder値を指定せずに、コンポジット・キー・クラスの主キー・フィールドを宣言した場合。

コンポジット・キー・クラスの次のプロパティに注意してください。

  • コンポジット・キー・クラスにshardKey=trueを含むフィールドが少なくとも1つ必要です。そうしないと、Spring Data Frameworkはエラーを生成します。
  • リポジトリとともにコンポジット・キー・クラスを(IDタイプとして)使用し、エンティティのアイデンティティを単一のオブジェクトで表すことができます。
  • フィールドを@transientとして注釈付けすると、フィールドの非永続状態を指定できます。
  • コンポジット・キー・クラスはネストできません。これによりエラーが生成されます。
  • コンポジット主キー・フィールドは自動生成できません。@NosqlId.autoGenerated=trueを設定すると、エラーが発生します。コンポジット・キーを使用する場合は、すべての読取り/書込みコールのキー値を管理する必要があります。キー値が設定されていない場合、Oracle NoSQL Databaseはエラーを生成します。

JSON列

エンティティの主キー・フィールド以外のすべてのフィールドは、次のルールに従ってNoSQL JSON値に変換されます。

  • Javaのスカラー値は、NoSQL JSONアトミック値に変換されます。
  • Javaのコレクションと配列構造は、NoSQL JSON配列に変換されます。
  • Javaの非スカラー値は、NoSQL JSONオブジェクトに再帰的に変換されます。
  • Javaのnull値は、NoSQL JSON NULL値に変換されます。
  • 複合値は、次の表に従ってNoSQL JSONオブジェクトに変換されます。

表1-5 Javaの型とNoSQL JSONの型のマッピング

Javaの型 Oracle NoSQL Database JSONデータ型での表現

java.lang.String

STRING

int

java.lang.Integer

INTEGER

long

java.lang.Long

LONG

double

java.lang.Double

float

java.lang.Float

DOUBLE

ノート:

Oracle NoSQL DatabaseFLOAT型はNoSQL SDK for Javaでは明示的に使用されていません。そのため、Javaのfloatjava.lang.FloatDOUBLE型にマップされます。

java.math.BigDecimal

java.math.BigInteger

NUMBER

boolean

java.lang.Boolean

BOOLEAN

byte[]

STRING - バイナリbase64エンコード表現。

java.util.Date

java.sql.Timestamp

java.time.Instant

STRING - ISO-8601 UTCタイムスタンプ・エンコード表現。

org.springframework.data.geo.Point

GeoJsonポイント

GeoJsonデータの詳細は、『SQLリファレンス・ガイド』GeoJsonデータについてを参照してください。

org.springframework.data.geo.Polygon

GeoJsonポリゴン

GeoJsonデータの詳細は、『SQLリファレンス・ガイド』GeoJsonデータについてを参照してください。

ノート:

ポリゴンは、適切な形式になるように次のルールに準拠する必要があります。適切な形式になっていないと、問合せでの使用時に無視されます。
  1. 線形リングは、4つ以上の位置を持つ閉じたLineStringです。
  2. 最初と最後の位置は同等で、同じ値が含まれている必要があります。
  3. 線形リングは、境界面の外側または境界面の内側(穴)のどちらです。
  4. 線形リングは、境界とする領域で右手の法則に従う必要があります。つまり、外側のリングの場合は位置を反時計回りに順序付けし、リングの内側(穴)の場合は位置を時計回りに順序付けする必要があります。

表に新しいポリゴンを挿入する前に、geo_is_geometry()ファンクションを使用して検証できます。ポリゴン・データが索引付けされている場合、索引パスの値が無効な行がある場合は、値がNULL、json nullまたはEMPTYでないかぎりエラーが発生します。

java.util.ArrayList

java.util.Collection

java.util.List

java.util.AbstractList

java.util.HashSet

java.util.Set

java.util.AbstractSet

java.util.TreeSet

java.util.SortedSet

java.util.NavigableSet

java.util.Array []

ARRAY(JSON)

ノート:

  • java.util.ArrayListオブジェクトは、java.util.Collectionjava.util.Listjava.util.AbstractListおよびjava.util.ArrayListの型のフィールドに対してインスタンス化されます。
  • java.util.HashSetオブジェクトは、java.util.Setjava.util.AbstractSetおよびjava.util.HashSetの型のフィールドに対してインスタンス化されます。
  • java.util.TreeSetオブジェクトは、java.util.SortedSetjava.util.NavigableSetおよびjava.util.TreeSetの型のフィールドに対してインスタンス化されます。

POJO<f1 T1, f2 T2...>

MAP(JSON)

java enum types

STRING

java.util.Map

java.util.NavigableMap

java.util.SortedMap

java.util.HashMap

java.util.LinkedHashMap

java.util.Hashtable

java.util.TreeMap

MAP(JSON)

ノート:

  • java.util.HashMapは、java.util.HashMap型のフィールドに対してインスタンス化されます
  • java.util.LinkedHashMapは、java.util.Mapおよびjava.util.LinkedHasMap型のフィールドに対してインスタンス化されます。
  • java.util.TreeMapは、java.util.NavigableMapjava.util.SortedMapおよびjava.util.TreeMapの型のフィールドに対してインスタンス化されます。

ノート:

サイクルが含まれているJavaデータ構造は、サポートも検出もされません。つまり、エンティティ・オブジェクトをルートからフィールドに向けて調べていったときに同じオブジェクトが2回出現した場合、そのオブジェクトはサイクルになります。