在我们项目中经常会遇到数据结构不定的情况,这时普通的关系型数据库不能满足我们的要求。Postgres为我们提供了jsonb
数据类型,我们可在此类型的字段存储json
数据,并可对此数据进行查询。本例将结合hibernate
,Spring Data JPA
,Spring Boot
来实现。
public class JsonbPostgresDialect extends PostgreSQL94Dialect {
public JsonbPostgresDialect() {
this.registerColumnType(Types.JAVA_OBJECT,"jsonb");
}
}
指定方言
spring.jpa.database-platform: com.example.jpajsonb.support.JsonbPostgresDialect
这里主要实现了Map
映射PGObject
(postgres对象类型),通过ObjectMapper
来实现两个数据类型的转换。
public class JsonbType implements UserType{
private final ObjectMapper mapper = new ObjectMapper();;
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.OTHER);
} else {
try{
st.setObject(index, mapper.writeValueAsString(value), Types.OTHER);
}catch (IOException e){
e.printStackTrace();
}
}
}
@Override
public Object deepCopy(Object originalValue) throws HibernateException {
if (originalValue != null) {
try {
return mapper.readValue(mapper.writeValueAsString(originalValue),
returnedClass());
} catch (IOException e) {
throw new HibernateException("Failed to deep copy object", e);
}
}
return null;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException {
PGobject o = (PGobject) rs.getObject(names[0]);
if (o.getValue() != null) {
try {
return mapper.readValue(o.getValue(),Map.class);
}catch (IOException e){
e.printStackTrace();
}
}
return new HashMap();
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
Object copy = deepCopy(value);
if (copy instanceof Serializable) {
return (Serializable) copy;
}
throw new SerializationException(String.format("Cannot serialize '%s', %s is not Serializable.", value, value.getClass()), null);
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return deepCopy(cached);
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return deepCopy(original);
}
@Override
public boolean isMutable() {
return true;
}
@Override
public int hashCode(Object x) throws HibernateException {
if (x == null) {
return 0;
}
return x.hashCode();
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.nullSafeEquals(x, y);
}
@Override
public Class> returnedClass() {
return Map.class;
}
@Override
public int[] sqlTypes() {
return new int[]{Types.JAVA_OBJECT};
}
}
先定义数据类型,再在字段上使用
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@TypeDef(name = "JsonbType", typeClass = JsonbType.class)
public class Person {
@Id
@GeneratedValue
private Long id;
@Column(columnDefinition = "jsonb")
@Type(type = "JsonbType")
private Map info;
}
通过postgres
原生sql语句查询,本例含义为json
数据info
的一个key
为name
的值等于。具体的JSON的sql查询方式请参考:
https://www.postgresql.org/docs/9.5/static/functions-json.html
public interface PersonRepository extends JpaRepository {
@Query(value = "select * from person where info ->> 'name' = :name" , nativeQuery = true)
List findByName(@Param("name") String name);
}
@Bean
CommandLineRunner saveAndReadJsonb(PersonRepository personRepository){
return e -> {
Person p = new Person();
Map m = new HashMap();
m.put("name","汪云飞");
m.put("age",11);
p.setInfo(m);
Person returnPerson = personRepository.save(p);
Map returnMap = returnPerson.getInfo();
for(Object entry :returnMap.entrySet()){
log.info(entry.toString());
}
};
}
@Bean
CommandLineRunner queryJsonb(PersonRepository personRepository){
return e -> {
List people = personRepository.findByName("吴亦凡");
for (Person person : people){
Map info = person.getInfo();
log.info(person.getId() + "/" + info.get("name") + "/" +info.get("age"));
}
};
}
http://www.wisely.top/2017/06/27/spring-data-jpa-postgresql-jsonb/
我的新书《从企业级开发到云原生微服务:Spring Boot 实战》已出版,内容涵盖了丰富Spring Boot开发的相关知识
购买地址:https://item.jd.com/12760084.html
主要包含目录有:
第一章 初识Spring Boot(快速领略Spring Boot的美丽)
第二章 开发必备工具(对常用开发工具进行介绍:包含IntelliJ IDEA、Gradle、Lombok、Docker等)
第三章 函数式编程
第四章 Spring 5.x基础(以Spring 5.2.x为基础)
第五章 深入Spring Boot(以Spring Boot 2.2.x为基础)
第六章 Spring Web MVC
第七章 数据访问(包含Spring Data JPA、Spring Data Elasticsearch和数据缓存)
第八章 安全控制(包含Spring Security和OAuth2)
第九章 响应式编程(包含Project Reactor、Spring WebFlux、Reactive NoSQL、R2DBC、Reactive Spring Security)
第十章 事件驱动(包含JMS、RabbitMQ、Kafka、Websocket、RSocket)
第11章 系统集成和批处理(包含Spring Integration和Spring Batch)
第12章 Spring Cloud与微服务
第13章 Kubernetes与微服务(包含Kubernetes、Helm、Jenkins、Istio)
多谢大家支持。