この章では、インターネット・データベース、オブジェクト・データベース、XMLデータベース、レガシー・データベースなどのNoSQLデータベース・システムに、Oracle TopLinkを使用してオブジェクトをマップする機能を説明します。
この章の内容は次のとおりです。
ユース・ケース
TopLinkでNoSQLデータ・ソースをユーザーが使用する必要があります。
解決方法
TopLinkは、複数のNoSQLデータ・ソースをサポートしています。このソリューションでは、Oracle NoSQLおよびMongoDBの使用を説明しています。
コンポーネント
TopLink 12c (12.1.2.0.0)以上。
注意: TopLinkのコア機能は、オープン・ソースのEclipse Foundationの永続性フレームワークであるEclipseLinkによって提供されています。EclipseLinkでは、Java Persistence API (JPA)、Java Architecture for XML Binding (JAXB)、および標準に基づいたその他の永続性テクノロジと、それらの標準の拡張が実装されます。TopLinkには、EclipseLinkのすべてに加え、Oracleの追加機能が含まれています。 |
NoSQLデータ・ソース。
JCAアダプタ。
例
関連情報については、次のEclipseLinkの例を参照してください。
EclipseLinkでは、JavaEE Connector Architectureを介して、NoSQLデータへのアクセスをサポートしています。(サード・パーティであるEclipseLinkが提供する、またはカスタム作成された)JCAを使用する必要があります。
NoSQLデータの多くは階層形式なので、一般に組込みオブジェクトが使用されています。一部のNoSQLアダプタでは、XMLデータをサポートしているので、NoSQLマップ済オブジェクトでは、XMLへのマッピング時にXMLマッピングを使用できます。
この項では、JSONドキュメントから、またJSONドキュメントにオブジェクトを変換する際の次のタスクについて説明します。
NoSQLデータにマッピングを行うには、EclipseLinkの@NoSQL
注釈およびXML要素の<no-sql>
を使用して構成します。@NoSQL
注釈では、クラスを非リレーショナル・データに対するマッピングとして定義します。@NoSQL
は、JPAエンティティまたは組込み可能クラスと使用できます。
@NoSQL
注釈では、データのdataType
およびdataFormat
を指定できます。dataType
は、使用しているNoSQLデータ・ソースにより異なります。
MongoDBの場合、dataType
は、JSONドキュメントのストア先のコレクション名です。
Oracle NoSQLの場合、dataType
は、主要なキー値の最初の部分になります。
dataFormat
は、保存されるデータのタイプ構造(データ形式)によります。
MongoDBでは、その構造化データベースにはMAPPED
を使用します。
Oracle NoSQLでは、MAPPED
(キー/値データ)またはXML
(単一XML文書の場合)を使用します。
例23-1に、@Entity
および@Embeddable
クラスで@NoSQL
を使用する方法を説明します。
例23-1 JSONでの@NoSql注釈の使用
@Entity @NoSQL(dataType="orders", dataFormat=DataFormatType.MAPPED) public class Order { @Id @GeneratedValue @Field(name="_id") private long id; @Basic @Field(name="description") private String description; @Embedded @Field(name="deliveryAddress") private Address deliveryAddress @ElementCollection @Field(name="orderLines") private List<OrderLine> orderLines; @ManyToOne @JoinField(name="customerId") private Customer customer; } @Embeddable @NoSQL(dataFormat=DataFormatType.MAPPED) public class OrderLine { @Field(name="lineNumber") private int lineNumber; @Field(name="itemName") private String itemName; @Field(name="quantity") private int quantity; }
EclipseLinkでは、非リレーショナル・データベースを使用する場合は、他のリレーショナル・エンティティ同様に、IDとして任意のフィールド(またはフィールドのセット)を使用できます。(アプリケーションに割り当てられた)自然IDを使用することも、(EclipseLinkによって割り当てられた)生成されたIDを使用することも可能です。
MongoDBでは、すべてのドキュメントに_id
フィールドも必要です。_id
フィールドがない場合、Mongoでは、UUID (Universally Unique Identifier)と類似したOID(オブジェクト識別子)を使用して_id
フィールドを自動的に生成します。
Mongo IDとして自然IDを使用する場合、他にリレーションシップをまったく指定せず、@Field
(または@Column
) 注釈を使用してフィールドを_id
と命名します。
次に例を示します。
@Field(name="_id") private long id;
生成されたMongo OIDをIDとして使用する場合、オブジェクトのIDフィールド・マッピングに単純に、@Id
、@GeneratedValue
および@Field(name="_id")
注釈を含めます。
@GeneratedValue
は、このID値の生成にMongo OIDを使用するようEclipseLinkに伝達します。Mongo OIDのかわりにUUIDを使用する場合は、@UUIDGenerator注釈を使用します。
注意: MongoDBでは、@SequenceGenerator または@TableGenerator や、IDENTITY 、TABLE およびSEQUENCE の生成タイプはサポートしていません。
Mongo OIDまたはUUIDのIDは数値ではなく、 |
次に例を示します。
@Id @GeneratedValue @Field(name="_id") private String id;
非リレーショナル・データベースの場合、EclipseLinkでは、オブジェクトをXMLやJSONなどの階層データにマップします。NoSQLでは、組込みデータや組込みコレクションを含むすべての既存のJPAマッピング注釈およびXMLをサポートしています。マッピング注釈(またはXML)を属性に定義しない場合、EclipseLinkではデフォルトのマッピングを使用します。
基本のマッピング
NoSQLのデフォルトはJPAのデフォルトであるため、最も単純なマッピングでも構成を行う必要はありません。Mongo BSONのドキュメントに使用されるフィールド名は、オブジェクト属性名(大文字)をミラーします。別のBSONフィールド名を使用するには、@Field
注釈を使用します。
注意: @Column や@JoinColumn は使用しないでください。かわりに@Field と@JoinField を使用します。また、@JoinTable および@CollectionTable 注釈はサポート対象外であるか不要です。 |
組込み値
組込み値を永続化するには、@Embedded
注釈を使用し、組込みコレクションには@ElementCollection
注釈を使用します。すべてのデータはXML文書に保存されるので、別途表(つまり、@CollectionTable
)を用意する必要はありません。また、組込みオブジェクトはドキュメントにネストされ、一意のフィールド名を必要としないので、@AttributeOverride
属性も不要です。
注意: 通常、正しくデフォルトが使用されるので、@Embedded 注釈は使用する必要がありません。
ただし、EclipseLinkでは |
リレーションシップ
(@OneToOne
、@ManyToOne
、@OneToMany
および@ManyToMany
などの)リレーションシップ注釈は、外部のリレーションシップでのみ使用します。ドキュメント内のリレーションシップでは、組込み値を使用する必要があります。
EclipseLinkの他のドキュメントに対する外部リレーションシップは、外部キーを使用し、完全にサポートされています。ターゲット・オブジェクトのIDは、ソース・オブジェクトのドキュメントにストアされます。コレクションには、IDのコレクションがストアされます。BSONドキュメントへの外部キー・フィールド名の定義には、@JoinField
注釈が使用されます。
注意: EclipseLinkでは、外部キーを両サイドに保存する必要があるため、非リレーショナル・データベースのリレーションシップに、mappedBy オプションはサポートしていません。 |
また、問合せを使用しリレーションシップ・マッピングを定義することも可能です。ただし、注釈のかわりにDescriptorCustomizer
を使用する必要があります。
例23-2 マッピングの例
@Basic private String description; @Basic private double totalCost = 0; @Embedded private Address billingAddress; @Embedded private Address shippingAddress; @ElementCollection private List<OrderLine> orderLines = new ArrayList<OrderLine>(); @ManyToOne(fetch=FetchType.LAZY) private Customer customer;
ロックに対するサポートは、NoSQLプラットフォームに依存しています。一部のNoSQLプラットフォームは、オプティミスティック・バージョン・ロックをサポートしています。
Oracle NoSQL: ロックはサポート対象されていません。
MongoDB: バージョン・ロックがサポートされています。
注意: MongoDBではトランザクションはサポートされていません。トランザクション中にエラーが発生した場合、前に書き込まれたオブジェクトはロール・バックされません。 |
NoSQLプラットフォームがロックをサポートしない場合、@Version
注釈(例23-3を参照)を使用し、merge()
操作時にオブジェクトを有効にする必要があります。
NoSQLで問合せを実行できるかどうかは、NoSQLプラットフォームに依存しています。一部のNoSQLデータ・ソースでは、それ独自の問合せ言語で動的な問合せがサポートされ、問合せが他ではまったくサポートされない場合があります。
Java Persistence Query Language (JPQL)は、JPAで定義されている問合せ言語です。JPQLは、読取り(SELECT
)、バルク更新(UPDATE
)および削除(DELETE
)に使用できます。JPQLは、(注釈やXMLを介して)NamedQuery
で使用するか、EntityManager createQuery()
APIを使用した動的問合せで使用します。
Oracle NoSQL: find()
、JPQLおよびCriteriaをIDまたはWHERE句なしでサポートしています。
MongoDB: 結合、下位選択、グループ化および特定のデータベース関数のサポートは除く、いくつかの制限付きでJPQLおよびCriteriaの問合せをサポートしています。
例23-5 MongoDB JPQLの例
Query query = em.createQuery("Select o from Order o where o.totalCost > 1000"); List<Order> orders = query.getResultList();
Query query = em.createQuery("Select o from Order o where o.description like 'Pinball%'"); List<Order> orders = query.getResultList();
Query query = em.createQuery("Select o from Order o join o.orderLines l where l.description = :desc"); query.setParameter("desc", "shipping"); List<Order> orders = query.getResultList();
Query query = em.createQuery("Select o.totalCost from Order o"); List<BigDecimal> orders = query.getResultList();
EclipseLinkは、persistence.xmlファイルを使用してNoSQLデータベースに接続します。特定のNoSQLプラットフォームを定義するには、<eclipselink.target-database>
プロパティを使用します。また、接続は<eclipselink.nosql.connection-spec>
プロパティで定義します。その他の接続値(db
、port
およびhost
も定義することができます。
注意: Mongoデータベースのクラスタに接続するには、host およびport にカンマで区切り値を入力します。 |
例23-9 MongoDBのpersistence.xmlの例
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_2_0.xsd" version="2.0">
<persistence-unit name="acme" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="org.eclipse.persistence.nosql.adapters.mongo.MongoPlatform"/>
<property name="eclipselink.nosql.connection-spec" value="org.eclipse.persistence.nosql.adapters.mongo.MongoConnectionSpec"/>
<property name="eclipselink.nosql.property.mongo.port" value="27017, 27017"/>
<property name="eclipselink.nosql.property.mongo.host" value="host1, host2"/>
<property name="eclipselink.nosql.property.mongo.db" value="acme"/>
</properties>
</persistence-unit>
</persistence>
この章のソリューションが実装されているその他のテクノロジおよびツールの詳細は、次の参考資料を参照してください。
Oracle TopLinkによるJAXBアプリケーションの開発
『Oracle TopLink Java Persistence API (JPA)拡張機能リファレンス』
http://wiki.eclipse.org/EclipseLink/Development/Incubator/Platform
の「EclipseLink Extensions Incubator」