Last active
April 2, 2020 17:39
-
-
Save mloza/a28c7950e8984e1512b8d43cd1eb791c to your computer and use it in GitHub Desktop.
Kod źródłowy do wpisu o polach JSONB w PostgreSQL i mapowaniu ich na encje Hibernate oraz Spring Data JPA znajdujący się pod adresem: https://blog.mloza.pl/wsparcie-dla-pola-typu-jsonb-w-postgresql-dla-spring-data-jpa-hibernate/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
blog_post=> select * from jsonb_entity; | |
id | jsonb_object | |
----+----------------------------------------------------------------------------------------------------------------------------------------------- | |
2 | {"intField": 10, "mapField": {"test": "value", "test2": "another value"}, "stringField": "String field tests", "intArrayField": [1, 3, 5, 9]} | |
(1 row) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
blog_post=> SELECT jsonb_object->>'stringField' FROM jsonb_entity WHERE jsonb_object->>'intField'='10'; | |
?column? | |
String field tests | |
(1 row) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Column | |
@Type(type = "pl.mloza.hibernate.CustomType") | |
private JsonbObject jsonbObject; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CustomPostgreSQL94Dialect extends PostgreSQL94Dialect { | |
public CustomPostgreSQL94Dialect() { | |
this.registerColumnType(Types.JAVA_OBJECT, "jsonb"); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CustomType implements UserType { | |
@Override | |
public int[] sqlTypes() { | |
return new int[]{Types.JAVA_OBJECT}; | |
} | |
@Override | |
public Class returnedClass() { | |
return JsonbObject.class; | |
} | |
@Override | |
public boolean equals(Object o, Object o1) throws HibernateException { | |
return Objects.equals(o, o1); | |
} | |
@Override | |
public int hashCode(Object o) throws HibernateException { | |
return o.hashCode(); | |
} | |
@Override | |
public Object nullSafeGet(ResultSet resultSet, String[] names, SharedSessionContractImplementor sharedSessionContractImplementor, Object owner) throws HibernateException, SQLException { | |
final String cellContent = resultSet.getString(names[0]); | |
if (cellContent == null) { | |
return null; | |
} | |
try { | |
final ObjectMapper mapper = new ObjectMapper(); | |
return mapper.readValue(cellContent.getBytes(Charset.defaultCharset()), returnedClass()); | |
} catch (final Exception ex) { | |
throw new RuntimeException("Failed to convert String to Invoice: " + ex.getMessage(), ex); | |
} | |
} | |
@Override | |
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int idx, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException { | |
if (value == null) { | |
preparedStatement.setNull(idx, Types.OTHER); | |
return; | |
} | |
try { | |
final ObjectMapper mapper = new ObjectMapper(); | |
final StringWriter w = new StringWriter(); | |
mapper.writeValue(w, value); | |
w.flush(); | |
preparedStatement.setObject(idx, w.toString(), Types.OTHER); | |
} catch (final Exception ex) { | |
throw new RuntimeException("Failed to convert Invoice to String: " + ex.getMessage(), ex); | |
} | |
} | |
@Override | |
public Object deepCopy(Object value) throws HibernateException { | |
try { | |
// use serialization to create a deep copy | |
ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
ObjectOutputStream oos = new ObjectOutputStream(bos); | |
oos.writeObject(value); | |
oos.flush(); | |
oos.close(); | |
bos.close(); | |
ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray()); | |
return new ObjectInputStream(bais).readObject(); | |
} catch (ClassNotFoundException | IOException ex) { | |
throw new HibernateException(ex); | |
} | |
} | |
@Override | |
public boolean isMutable() { | |
return true; | |
} | |
@Override | |
public Serializable disassemble(Object o) throws HibernateException { | |
return (Serializable) o; | |
} | |
@Override | |
public Object assemble(Serializable serializable, Object o) throws HibernateException { | |
return serializable; | |
} | |
@Override | |
public Object replace(Object original, Object target, Object owner) throws HibernateException { | |
return original; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Entity | |
public class JsonbEntity { | |
@Id | |
@GeneratedValue | |
private long id; | |
@Column | |
private JsonbObject jsonbObject; //pole które będzie zapisane jako JSONB | |
// setters, getters, toString... | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class JsonbObject implements Serializable { | |
private int intField; | |
private String stringField; | |
private int[] intArrayField; | |
private Map<String, String> mapField = new HashMap<>(); | |
// setters, getters etc. | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public interface JsonbRepository extends CrudRepository<JsonbEntity, Long> { } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@SpringBootTest | |
public class RepositoryTest extends AbstractTestNGSpringContextTests { | |
@Autowired | |
private JsonbRepository repository; | |
@Test | |
public void shouldSaveDataInJSONB() { | |
JsonbObject jsonbObject = new JsonbObject() | |
.setIntArrayField(new int[]{1, 3, 5, 9}) | |
.setIntField(10) | |
.setStringField("String field tests"); | |
jsonbObject | |
.getMapField() | |
.put("test", "value"); | |
jsonbObject.getMapField().put("test2", "another value"); | |
JsonbEntity jsonbEntity = new JsonbEntity() | |
.setJsonbObject(jsonbObject); | |
JsonbEntity entity = repository.save(jsonbEntity); | |
Optional<JsonbEntity> jsonbObjectNew = repository.findById(entity.getId()); | |
System.out.println(jsonbObjectNew); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment