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<AgentProfileOuter,String>
应该类似于CrudRepository<AgentProfileOuter,long>
,因为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”不存在