Hibernate and PostgreSQL JSON Type

Hello Habr! This article will not be deep analysis of the json type in PostgreSQL or another useless trying to compare this possibility with PostgreSQL NoSQL database MongoDB. I'll just tell you about how to use Hibernate and PostgreSQL json. Think who else it could be useful.

/ >

Object within the entity


Suppose you have a relational data model. It may be a situation that for some of the entities you want to store any object(document if you want). Of course you can extend this object model data of one(or maybe several) entity, or simply store this object as an array of bytes. But PostgreSQL had a data type of json able to store the json object in accordance with RFC 4627. Was wondering how to use it, and what opportunities it can give. When you first access the google I found some unstructured posts and Q&A which was explaining something, but did not give the full picture. A little hesitated a moment and understand what was happening, I came to the conclusion that the use of these fields is very comfortable and decided to create small library that will simplify use of json types. Below I will tell you how to use it, there is still little comparison with the first coming to mind alternatives.

Dialect


Of course any support of this type in the standard dialect and not talking. Really I would like that hibernate itself recognizes the type and undertook the validation/updating of the scheme. Therefore the library contains dialect JsonPostgreSQLDialect expanding PostgreSQL9Dialect. Just use this dialect in your persistance.xml.

Object storage


Store in a json field as an object and just Map. If you want to store the object you inherit a class you are going to store PGJsonObject
the
public class PGJsonObject extends CacheObject {
...
}

and make using annotations to the type definition in your Entity:
the
@Entity
@Are typedefs({@TypeDef( name= "JsonObject", typeClass = CacheObject.class)})
public class Product {
...
@Type(type = "JsonObject")
public CacheObject getCache() {
return cache;
}
}

If it breaks your inheritance scheme, you can create a separate from your class to hold the class responsible for type. He will inherit all the same PGJsonObject, and should override the returnedClass () which will return the class of the object you want to store. This class then will need to use in your Entity to determine the type.
the
public class JsonCustomType extends PGJsonObject {

@Override
public Class returnedClass() {
return Custom.class;
}

}

Then the type definition in the Entity would look like this:
the
@Entity
@Are typedefs({@TypeDef( name= "JsonObject", typeClass = JsonCustomType.class)})
public class Product {
...
@Type(type = "JsonObject")
public Custom getCustom() {
return custom.
}
}

If you are going to store a Map, simply use the existing library type JsonMapType.

Recommendations


the
    the
  • Be careful about changing the data object. If the object that you are storing is not immutable, then any change that you make will be saved to the database(of course if the transaction does not roll back), so if you don't want to save the changes, make a copy
  • the
  • Test your native queries. Make sure they indicate your Entity


the benefits of JSON fields


Immediately comes to mind 2 alternative implementations
the
    the
  • Extend the database schema for the object
  • the
  • to store a byte array

The first option can greatly complicate your data model, if the object has a deep hierarchy. If the object stores a large array, e.g. an array of points, the grid points can have a huge number of entries that can slow down the sample. Also under this option, the application should know all about the data schema that would pull them from the table.
In the second embodiment does not require schema extensions, but the information stored in this field is absolutely not representative and not indexed. And as in the previous case, the application must know about the structure of the stored data, only this time for proper deserialization.
Also the use of json field can serve as a great help in the task of integration. Keeping in one place field in the json object, in the other you can pull out his Map, and Vice versa. If you know only part of the structure of the object, you can deserialize only known and desired part of the json object into java object, and the rest either ignore or deserialize again to the Map.

Project source code can be found on github. While the project is raw. I hope in the future to simplify the use, to enter annotations.
Article based on information from habrahabr.ru

Comments

Popular posts from this blog

Powershell and Cyrillic in the console (updated)

Active/Passive PostgreSQL Cluster, using Pacemaker, Corosync

Automatic deployment ElasticBeanstalk using Bitbucket Pipelines