There are already several answers and I am pretty sure they work for several cases. I don't wanted to use any more dependencies I don't know, so I look for another solution.
The important parts are the AttributeConverter it maps the jsonb from the db to your object and the other way around. So you have to annotate the property of the jsonb column in your entity with @Convert and link your AttributeConverter and add @Column(columnDefinition = "jsonb") as well, so JPA knows what type this is in the DB. This should already make it possible to start the spring boot application. But you will have issues, whenever you try to save() with the JpaRepository. I received the message:
PSQLException: ERROR: column "myColumn" is of type jsonb but
expression is of type character varying.
Hint: You will need to rewrite or cast the expression.
This happens because postgres takes the types a little to serious.
You can fix this by a change in your conifg:
datasource.hikari.data-source-properties: stringtype=unspecified
datasource.tomcat.connection-properties: stringtype=unspecified
Afterwards it worked for me like a charm, and here is a minimal example.
I use JpaRepositories:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Integer> {
}
The Entity:
import javax.persistence.Column;
import javax.persistence.Convert;
public class MyEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
protected Integer id;
@Convert(converter = MyConverter.class)
@Column(columnDefinition = "jsonb")
private MyJsonObject jsonContent;
}
The model for the json:
public class MyJsonObject {
protected String name;
protected int age;
}
The converter, I use Gson here, but you can map it however you like:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
@Converter(autoApply = true)
public class MyConverter implements AttributeConverter<MyJsonObject, String> {
private final static Gson GSON = new Gson();
@Override
public String convertToDatabaseColumn(MyJsonObject mjo) {
return GSON.toJson(mjo);
}
@Override
public MyJsonObject convertToEntityAttribute(String dbData) {
return GSON.fromJson(dbData, MyJsonObject.class);
}
}
SQL:
create table my_entity
(
id serial primary key,
json_content jsonb
);
And my application.yml (application.properties)
datasource:
hikari:
data-source-properties: stringtype=unspecified
tomcat:
connection-properties: stringtype=unspecified
Session
or something to run the query without the@Repository
? – Carafeapplication.properties
. If I don't use it I need to configurate all in a old fashion way (Session, DAO, Connection, EntityManager, etc... ) and I don't want to. – Carafeinsert
function to wrap thejsonb
type exposing the function parameter as a text and then inserting as jsonb. Just using the@Query
asselect insert_data( my_string_json )
. Done. – CarafeI don't need to use
. Plase tell ushow
... – CarafeJdbcTemplate
that is all you need to execute the same SQL statement. – Petronellaspring-boot-starter-data-jpa
addspring-boot-starter-jdbc
leave the datasource stuff. Instead of calling the method on your interface (ditch the interface) dojdbcTemplate.executeUpdate("insert into dnit(id, data) VALUES (?,to_json(?))", id, data);
– Petronella