querydsl查询pg数据库 jsonb类型字段 多了一个type问题处理

问题

工作中遇到一个问题,QueryDSL查询 pg数据库的一个表,表中一个某个字段类型是jsonb,jsonb的存取和json在java层面上没有什么区别,但是得到的数据,会多余了一个type字段。比如:

数据库存的是: 
{"wubi": "tgrpss", "pinyin": "teshuzhidingjigou",  "shoupin": "tszdjg"}

经过QueryDSL查出来的数据就变成了下面这样:
	{
        "type": "jsonb",
        "value": "{\"wubi\": \"tgrpss\", \"pinyin\": \"teshuzhidingjigou\", \"shoupin\": \"tszdjg\"}"
      }

这就很难受了,前端用起来极不方便。

原因

解决过程少不了看源码,经过源码分析,流程大概这样:

  • 前端调用接口,接口方法中,使用的是 QueryDSL,通过pgConnection驱动进行sql查询,查看打印sql,再正常不过了。

  • pgConnection驱动从pg中查出结果,在处理过程中,通过层层映射,这里就不细说了,实际上并没有映射到相关的类型,走的default路径,最后给 QueryDSL 返回一个 org.postgresql.util.PGobject 对象。

	public class PGobject implements Serializable, Cloneable {
    	protected String type;
    	protected String value;

    	public PGobject() {
    	}
    	...
	}

querydsl查询pg数据库 jsonb类型字段 多了一个type问题处理_第1张图片

  • QueryDSL 得到对象后,处理很简单,就是通过反射,讲查询的到数据,放到一个前端接口映射的一个对象中。

  • 最终前端拿到这个对象,是一个PGobject 。

解决思路

首先, pgConnection驱动从pg库中取数据这个过程,我们是没有办法处理的,这个是pg驱动jar来处理的,处理这个不划算。
第二,QueryDSL 通过反射, PGobject 写到前端查询需要的对象(OBJ)中。这一步也是QueryDSL的jar来处理的,反射过程很简单,也没有重构的必要。

所以,只能冲前端拿到 OBJ 之前,做处理了。处理这个,SpringMVC早就有一套了。

Spring MVC JSON自己定义类型转换

继承 JsonSerializer 抽奖类,重写 serialize方法,如下:


import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.postgresql.util.PGobject;

import java.io.IOException;
import java.util.Objects;

public class PgObjectJsonSerializer extends JsonSerializer {

    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        if (Objects.isNull(o)) {
            return;
        }
        if (o instanceof PGobject) {
            PGobject pgO = (PGobject) o;
            if ("jsonb".equals(pgO.getType())) {
                jsonGenerator.writeObject(pgO.getValue());
            }
        }
    }
}

 
  

在返回给前端的对象上使用即可:

public class XXX implements Serializable { 

    @JsonSerialize(using = PgObjectJsonSerializer.class)
    private transient Object xxx;
    ...
   }

你可能感兴趣的:(issues,java,web,PGobject,jsonb处理返回值type)