Overview
Ebean provides @DbJson
and @DbJsonB
for mapping properties as
JSON documents into Postgres JSON, Postgres JSONB, CLOB, VARCHAR or BLOB.
Both Postgres
and Oracle
(and shortly MySql
) provide
functions/expressions for querying and manipulating the JSON.
Ebean also has ElasticSearch
integration so even without the built in database
support we can use that integration to effectively replicate to ElasticSearch and use it
to search our data.
Mixing structured and unstructured
What these capabilities do is enable designers/developers to mix unstructured (or semi-structured) document content with our typically highly structured data.
An example use case might be storing 'user preferences' where the data naturally comes in as JSON, has potentially deep nesting and where we only need limited queries/expressions on the document attributes. In this type of case the use of unstructured document storage as JSON can be a good fit.
Mapping simple types
If the mapping is to String
, Long
or Map<String,Object>
types
then Ebean will use it's built in JSON support to handle the marshalling to/from JSON.
@DbJsonB
Map<String,Object> content;
@DbJsonB
List<String> contents;
With these types note that Ebean will use ModifyAware
collections so that it knows if the
property is dirty
and needs to be included in an update. If the type is not ModifyAware then
it must be treated as dirty and included in an update.
Mapping with Jackson ObjectMapper
If the type mapped is not one of String
, Long
or Map<String,Object>
types
then Ebean will use Jackson ObjectMapper to handle the marshalling to/from JSON.
In this case jackson-databind
becomes a required dependency.
// Jackson ObjectMapper used here
@DbJsonB
Map<String,SomePojo> content;
// Jackson ObjectMapper used here
@DbJsonB
SomePojo content;
Note that when we use Jackson for marshalling the property type is not ModifyAware
and that
means that it must be treated as dirty
and included in updates. It will only be included in
updates if the property is actually loaded of course and so if you know a use case will not update the content
it can be worth while to not load it in the first place (with the additional benefit that it won't be automatically
included in the update).
ServerConfig
An ObjectMapper instance can be configured on ServerConfig via setObjectMapper()
. If an ObjectMapper is
not specified in this way an instance will be created for use by Ebean (If Jackson ObjectMapper is
detected in the classpath).
Fallback mapping
When Postgres is not used then fallback is to store JSON into VARCHAR, CLOB or BLOB database types.
If the length
attribute is specified like @DbJson(length=1000)
or @DbJsonB(length=1000)
then VARCHAR is the fallback type and the length defined is the
length of the varchar column definition.
// fallback to store in VARCHAR(800)
@DbJson(length=800)
Map<String,Object> content;
The storage can be explicitly defined using the storage
attribute.
// explicitly store using BLOB
@DbJson(storage = DbJsonType.BLOB)
Map<String,Object> content;
The default fallback for JSON and JSONB types is CLOB and this is used when both the length and storage attributes are not defined.
Query expressions
Refer to json-in-db documentation for details on the query expressions and how those translate for both Postgres and Oracle expressions.