Spring Boot与Postgres jsonb集成

3

我正在编写一个基于Spring Boot的应用程序,尝试将数据存储和检索到PostGreSQL db中的jsonb列中。 在保存记录时它可以正常工作,但是当我编写基本的方法来查找其存储库接口中的记录时,就会出现问题,例如:

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个回答

1
我认为这是因为Mongo和PostGreSQL都以不同的方式组织数据。从Mongo的角度来看,AgentProfileOuter是一个以JSON格式保存为键值对的文档。您在AgentProfile类中的每个字段都是Mongo的键,无论它是另一个/子对象。然而,对于PostGreSQL来说,整个AgentProfile对象只是一个String blob列,因为您没有将此类标记为@Entity并且它没有主键。因此,当您尝试搜索像pcpAgentId=someid这样的内容时,对于PostGreSQL来说就没有任何意义。这是我的猜测,请通过检查PostGreSQL中的数据结构来验证。

还注意到CrudRepository<AgentProfileOuter,String>应该像CrudRepository<AgentProfileOuter,long>一样,因为AgentProfilOuter类的主键是long。


这意味着我无法使用SpringBoot从Postgres查询JSON字段。我在互联网上也找不到任何有用的信息。 - user3540695
您可以将AgentProfile定义为AgentProfileOuter的子实体,这将在两个单独的表中保存每个实体。如果这样做,您的查询将按原样工作。另一个选项是使用like查询/ spring-boot方法,这将需要荒谬的时间来查询。归根结底,您想要使用哪个数据库(Mongo vs Postgre)取决于您打算如何使用数据。 - techtabu
最近看起来在Postgres的JSONB类型中,以CRUD方式查询数据仍然不可行,唯一的方法是实现本地查询。 - kensai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接