I have a table with a column of type JSON in my PostgreSQL DB (9.2). I have a hard time to map this column to a JPA2 Entity field type.
I tried to use String but when I save the entity I get an exception that it can't convert character varying to JSON.
What is the correct value type to use when dealing with a JSON column?
@Entity
public class MyEntity {
private String jsonPayload; // this maps to a json column
public MyEntity() {
}
}
A simple workaround would be to define a text column.
I tried many methods I found on the Internet, most of them are not working, some of them are too complex. The below one works for me and is much more simple if you don't have that strict requirements for PostgreSQL type validation.
Make PostgreSQL jdbc string type as unspecified, like
<connection-url> jdbc:postgresql://localhost:test?stringtype=unspecified </connection-url>
If you're interested, here are a few code snippets to get the Hibernate custom user type in place. First extend the PostgreSQL dialect to tell it about the json type, thanks to Craig Ringer for the JAVA_OBJECT pointer:
Next implement org.hibernate.usertype.UserType. The implementation below maps String values to the json database type, and vice-versa. Remember Strings are immutable in Java. A more complex implementation could be used to map custom Java beans to JSON stored in the database as well.
Now all that's left is annotating the entities. Put something like this at the entity's class declaration:
Then annotate the property:
Hibernate will take care of creating the column with json type for you, and handle the mapping back and forth. Inject additional libraries into the user type implementation for more advanced mapping.
Here's a quick sample GitHub project if anyone wants to play around with it:
https://github.com/timfulmer/hibernate-postgres-jsontype
There is an easier to to do this which doesn't involve creating a function by using
WITH INOUT
In case someone is interested, you can use JPA 2.1
@Convert
/@Converter
functionality with Hibernate. You would have to use the pgjdbc-ng JDBC driver though. This way you don't have to use any proprietary extensions, dialects and custom types per field.I had a similar problem with Postgres (javax.persistence.PersistenceException: org.hibernate.MappingException: No Dialect mapping for JDBC type: 1111) when executing native queries (via EntityManager) that retrieved json fields in the projection although the Entity class has been annotated with TypeDefs. The same query translated in HQL was executed without any problem. To solve this I had to modify JsonPostgreSQLDialect this way:
Where myCustomType.StringJsonUserType is the class name of the class implementing the json type (from above, Tim Fulmer answer) .
See PgJDBC bug #265.
PostgreSQL is excessively, annoyingly strict about data type conversions. It won't implicitly cast
text
even to text-like values such asxml
andjson
.The strictly correct way to solve this problem is to write a custom Hibernate mapping type that uses the JDBC
setObject
method. This can be a fair bit of hassle, so you might just want to make PostgreSQL less strict by creating a weaker cast.As noted by @markdsievers in the comments and this blog post, the original solution in this answer bypasses JSON validation. So it's not really what you want. It's safer to write:
AS IMPLICIT
tells PostgreSQL it can convert without being explicitly told to, allowing things like this to work:Thanks to @markdsievers for pointing out the issue.