概要

Postgres と Oracle は、データベース内に格納された JSON を広範囲にサポートしています。どちらも、ドキュメントパス式を使用してクエリを作成するための多くのサポートを提供します。

Ebean は、@DbJson@DbJsonB を使用して、Postgres JSON、JSONB タイプ、標準の Varchar、Clob、Blob タイプを含むさまざまなデータベースタイプに JSON ドキュメントをマッピングするためのマッピングサポートを提供します。 Postgres JSON、JSONB タイプ、標準の Varchar、Clob、Blob タイプを含むさまざまなデータベースタイプに JSON ドキュメントをマッピングするためのマッピングサポートを提供します。このマッピングは、サポートされているすべてのデータベースで使用できますが、Postgres と Oracle は、クエリ where 句に JSON 式を含めるためのサポートを提供します。

Postgres と Oracle はどちらも、JSON 式を使用してクエリを記述することをサポートしており、Ebean は最も一般的なクエリ式を公開しています。

マッピング

すべてのデータベースに対して、JSON ドキュメントはエンティティブーンにマッピングし、データベースに保存してデータベースから読み込むことができます。

@DbJsonB

エンティティブーンでは、プロパティに @DbJsonB でアノテーションを付けることができ、そのプロパティが JSONB データベースタイプにマッピングされることを示します。Postgres 以外のデータベースでは、これはデータベースの Clob にマッピングされます。

@Entity
@Table(name="p_doc")
public class SimpleDoc extends Model {

  @Id
  Long id;
  ...

  @DbJsonB
  Map<String,Object> content;

  // Ordinary bean - use Jackson object mapper
  @DbJsonB
  PlainBean plainBean;

@DbJson

エンティティブーンでは、プロパティに @DbJson でアノテーションを付けることができ、そのプロパティが JSON データベースタイプにマッピングされることを示します。Postgres 以外のデータベースでは、これはデータベースの Clob にマッピングされます。

@Entity
@Table(name="p_doc")
public class SimpleDoc extends Model {

  @Id
  Long id;
  ...

  @DbJson
  Map<String,Object> content;

  // Ordinary bean - use Jackson object mapper
  @DbJson
  PlainBean plainBean;

保存と検索

JSON コンテンツをコンテンツプロパティに配置して保存し、通常の方法でフェッチします。

String rawJson = "{\"docName\":\"My document\", \"docScore\":234, \"title\":\"Some title\"}";

// get the JSON into a map using Jackson or similar tool.
// Ebean has EJson which using Jackson core which can be used
// to parse JSON content
Map<String, Object> content = EJson.parseObject(rawJson);

SimpleDoc doc = new SimpleDoc();
doc.setName("doc1");
doc.setContent(content);

// save to db
doc.save();

// fetch from db
SimpleDoc doc1 = SimpleDoc.find.byId(doc.getId());

assertEquals("My document", doc1.getContent().get("docName"));

クエリ式

PostgresOracle は、特定のパスが EXISTS であるかどうかをテストしたり、パスの値をテストしたりするための path 式を使用できるようにする式を提供します。

Ebean ExpressionList には以下の式があります。

/**
 * Path exists - for the given path in a JSON document.
 */
ExpressionList<T> jsonExists(String propertyName, String path);

/**
 * Path does not exist - for the given path in a JSON document.
 */
ExpressionList<T> jsonNotExists(String propertyName, String path);

/**
 * Equal to expression for the value at the given path in the JSON document.
 */
ExpressionList<T> jsonEqualTo(String propertyName, String path, Object value);

/**
 * Not Equal to - for the given path in a JSON document.
 */
ExpressionList<T> jsonNotEqualTo(String propertyName, String path, Object val);

/**
 * Greater than - for the given path in a JSON document.
 */
ExpressionList<T> jsonGreaterThan(String propertyName, String path, Object val);

/**
 * Greater than or equal to - for the given path in a JSON document.
 */
ExpressionList<T> jsonGreaterOrEqual(String propertyName, String path, Object val);

/**
 * Less than - for the given path in a JSON document.
 */
ExpressionList<T> jsonLessThan(String propertyName, String path, Object val);

/**
 * Less than or equal to - for the given path in a JSON document.
 */
ExpressionList<T> jsonLessOrEqualTo(String propertyName, String path, Object val);

Postgres 式

Ebean は Postgres ->>#>> 演算子を使用して、JSON 式をサポートします。

存在式

Postgres Ebean の jsonExists() jsonNotExists() 式では、パス値を使用して ->> または #>> および IS NULLIS NOT NULL を使用します。

List<SimpleDoc> list = new QSimpleDoc().query()
.where()
.jsonExists("content", "path.other")
.findList();

その後、関数は次のような Ebean クエリで使用できます。

select t0.id c0, ...
where (t0.content #>> '{path,other}') is not null

値式

Postgres の Ebean の値式(jsonEqualTo()jsonGreaterThan() など)では、パスに応じて ->> または #>> 演算子を使用してから、テストする値に応じて結果をキャストします。つまり、テストされる値が Integer または Long の場合、DB パス式は ::INTEGER にキャストされ、::DECIMAL::BOOLEAN にも同様のキャストがあります。

List<SimpleDoc> list = new QSimpleDoc().query()
  .where()
  .jsonEqualTo("content", "path.other", 34)
  .findList();
select t0.id c0, ...
where (t0.content #>> '{path,other}')::INTEGER = ?

Oracle の式

Ebean は Oracle の json_existsjson_value 関数を使用して、Ebean の JSON 式をサポートします。

存在式

Oracle Ebean の jsonExists() 式は Oracle json_exists 関数を使用します。

List<SimpleDoc> list = new QSimpleDoc().query()
  .where()
  .jsonExists("content", "path.other")
  .findList();

その後、関数は次のような Ebean クエリで使用できます。

select t0.id c0, ...
where json_exists(t0.content, '$.path.other')

値式

Oracle Ebean の値の jsonEqualTo() jsonGreaterThan() などは Oracle json_value 関数を使用します。

List<SimpleDoc> list = new QSimpleDoc().query()
  .where()
  .jsonEqualTo("content", "path.other", 34)
  .findList();
select t0.id c0, ...
where json_value(t0.content, '$.path.other') = ?

未加工の式

提供された式が要件と一致しない場合は、raw() 式を使用できます。

List<SimpleDoc> docs = SimpleDoc.find.where()
  // pass a raw expression through - property names are translated to
  // db columns but everything else is passed through to the DB
  .raw("content#>'{docName}' ? 'rob doc'")
  .findList();