Spring Boot 与 Postgres jsonb 的集成

Posted

技术标签:

【中文标题】Spring Boot 与 Postgres jsonb 的集成【英文标题】:Spring boot integration with Postgres jsonb 【发布时间】:2016-11-02 09:33:07 【问题描述】:

我正在编写一个基于 Spring Boot 的应用程序,并尝试在其 jsonb 列中存储和检索 PostGreSQL db 中的数据。 在保存记录时它工作正常,但是当我编写基本方法在它的存储库界面中查找记录时,如下所示:-

public interface AgentProfileRepository extends CrudRepository<AgentProfileOuter,String> 

    public AgentProfileOuter findByJdataPcpAgentId(String id);

 

然后服务器在重新启动时开始给出此异常:-

Caused by: java.lang.IllegalStateException: Illegal attempt to dereference path source [null.jdata] of basic type
    at org.hibernate.jpa.criteria.path.AbstractPathImpl.illegalDereference(AbstractPathImpl.java:98) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at org.hibernate.jpa.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:191) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final]
    at org.springframework.data.jpa.repository.query.QueryUtils.toExpressionRecursively(QueryUtils.java:524) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.QueryUtils.toExpressionRecursively(QueryUtils.java:478) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.getTypedPath(JpaQueryCreator.java:300) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryCreator$PredicateBuilder.build(JpaQueryCreator.java:243) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]
    at org.springframework.data.jpa.repository.query.JpaQueryCreator.toPredicate(JpaQueryCreator.java:148) ~[spring-data-jpa-1.9.4.RELEASE.jar:na]

想知道的一点是,当我尝试通过 id 查找它时,它是 postgres 中的一个普通数字列,它可以正常工作,但如果我尝试通过 json 中的键查找则不行。这可以在 MongoDB 上成功运行。

以下是编写的 bean 类:-

AgentProfileOuter.java

import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;



@Table(name = "Agentbonds")
@Entity

public class AgentProfileOuter 


     @GeneratedValue(strategy=GenerationType.AUTO)
     @Id
    private long id;

    @Convert(converter = ConverterAgent.class)
    @Column(name="jdata")
    private AgentProfile jdata;





    public long getId() 
        return id;
    

    public void setId(long id) 
        this.id = id;
    

    public AgentProfile getJdata() 
        return jdata;
    

    public void setJdata(AgentProfile jdata) 
        this.jdata = jdata;
    


AgentProfile.java

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Generated;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Table;

import org.springframework.data.annotation.Id;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder(
    "pcpAgentId",
    "name",
    "bio",
    "phone",
    "email",
    "sms",
    "imageUrl"
)





public class AgentProfile 



    @JsonProperty("pcpAgentId")
    private String pcpAgentId;

    /*
    public void setAdditionalProperties(Map<String, Object> additionalProperties) 
        this.additionalProperties = additionalProperties;
    
    */

    @JsonProperty("name")
    private String name;
    @JsonProperty("bio")
    private String bio;
    @JsonProperty("phone")
    private String phone;
    @JsonProperty("email")
    private String email;
    @JsonProperty("sms")
    private String sms;
    @JsonProperty("imageUrl")
    private String imageUrl;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    /**
     * 
     * @return
     *     The pcpAgentId
     */
    @JsonProperty("pcpAgentId")
    public String getpcpAgentId() 
        return pcpAgentId;
    

    /**
     * 
     * @param pcpAgentId
     *     The pcpAgentId
     */
    @JsonProperty("pcpAgentId")
    public void setAgentId(String pcpAgentId) 
        this.pcpAgentId = pcpAgentId;
    

    /**
     * 
     * @return
     *     The name
     */
    @JsonProperty("name")
    public String getName() 
        return name;
    

    /**
     * 
     * @param name
     *     The name
     */
    @JsonProperty("name")
    public void setName(String name) 
        this.name = name;
    

    /**
     * 
     * @return
     *     The bio
     */
    @JsonProperty("bio")
    public String getBio() 
        return bio;
    

    /**
     * 
     * @param bio
     *     The bio
     */
    @JsonProperty("bio")
    public void setBio(String bio) 
        this.bio = bio;
    

    /**
     * 
     * @return
     *     The phone
     */
    @JsonProperty("phone")
    public String getPhone() 
        return phone;
    

    /**
     * 
     * @param phone
     *     The phone
     */
    @JsonProperty("phone")
    public void setPhone(String phone) 
        this.phone = phone;
    

    /**
     * 
     * @return
     *     The email
     */
    @JsonProperty("email")
    public String getEmail() 
        return email;
    

    /**
     * 
     * @param email
     *     The email
     */
    @JsonProperty("email")
    public void setEmail(String email) 
        this.email = email;
    

    /**
     * 
     * @return
     *     The sms
     */
    @JsonProperty("sms")
    public String getSms() 
        return sms;
    

    /**
     * 
     * @param sms
     *     The sms
     */
    @JsonProperty("sms")
    public void setSms(String sms) 
        this.sms = sms;
    

    /**
     * 
     * @return
     *     The imageUrl
     */
    @JsonProperty("imageUrl")
    public String getImageUrl() 
        return imageUrl;
    

    /**
     * 
     * @param imageUrl
     *     The imageUrl
     */
    @JsonProperty("imageUrl")
    public void setImageUrl(String imageUrl) 
        this.imageUrl = imageUrl;
    

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() 
        return this.additionalProperties;
    

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) 
        this.additionalProperties.put(name, value);
    


非常感谢您对此的任何帮助。

【问题讨论】:

【参考方案1】:

我认为,这是因为 Mongo 和 PostGreSQL 如何构建数据。从 Mongo 的角度来看,AgentProfileOuter 是一个以 JSON 格式保存为 key:value 的文档。 AgentProfile 类中的每个字段都是 Mongo 的关键,无论它是另一个/子对象。但是,对于 PostGreSQL,整个 AgentProfile 对象只是 String blob 的一列,因为您没有将此类标记为 @Entity 并且它没有主 ID。因此,当您尝试搜索 pcpAgentId=someid 之类的内容时,PostGreSQL 没有任何意义。这是我的猜测,通过检查 PostGreSQL 中的数据结构来验证。

还注意到CrudRepository&lt;AgentProfileOuter,String&gt; 应该类似于CrudRepository&lt;AgentProfileOuter,long&gt;,因为AgentProfilOuter 类的主键很长。

【讨论】:

这意味着我无法使用 springboot 从 postgres 查询 json 字段。我在互联网上也找不到任何有用的东西。 您可以将AgentProfile 定义为AgentProfileOuter 的子实体,这会将每个实体保存在两个单独的表中。如果这样做,您的查询将按原样工作。另一种选择,您可以使用like query/spring-boot 方法,这将花费大量时间进行查询。归根结底,您要使用哪个数据库(Mongo 与 Postgre)取决于您打算如何使用数据。 现在看来,在postgres中对于JSONB类型仍然无法以CRUD方式查询数据,唯一的方法是实现原生查询。

以上是关于Spring Boot 与 Postgres jsonb 的集成的主要内容,如果未能解决你的问题,请参考以下文章

如何对接一个与 AWS RDS Postgres 实例连接的 Spring Boot 应用程序? [关闭]

Docker Compose + Spring Boot + Postgres 连接,导致报错

Spring Boot 和 Postgres:关系“sub_comment”不存在

为啥 spring-boot 和 postgres 连接会在一段时间后断开?

序列不存在 - Postgres/Spring Boot

在带有 Spring-boot 的 postgres 中使用整数数组