當前位置:
首頁 > 知識 > Spring Data JPA與PostgreSQL的jsonb類型集成與支持

Spring Data JPA與PostgreSQL的jsonb類型集成與支持

在我們項目中經常會遇到數據結構不定的情況,這時普通的關係型資料庫不能滿足我們的要求。Postgres為我們提供了jsonb數據類型,我們可在此類型的欄位存儲json數據,並可對此數據進行查詢。本例將結合hibernate,Spring Data JPA,Spring Boot來實現。

1. 自定義方言

public class JsonbPostgresDialect extends PostgreSQL94Dialect {

public JsonbPostgresDialect {
this.registerColumnType(Types.JAVA_OBJECT,"jsonb");
}
}

指定方言

spring.jpa.database-platform: com.example.jpajsonb.support.JsonbPostgresDialect

2. 自定義jsonb數據類型

這裡主要實現了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};
}

}

3. 聲明使用

先定義數據類型,再在欄位上使用

@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;
}

4.Repository

通過postgres原生sql語句查詢,本例含義為json數據info的一個keyname的值等於。具體的JSON的sql查詢方式請參考:

public interface PersonRepository extends JpaRepository {
@Query(value = "select * from person where info ->> "name" = :name" , nativeQuery = true)
List findByName(@Param("name") String name);
}

5. 保存和讀取測試

@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);
}
};
}

6. 查詢測試

@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"));
}
};
}

7. 源碼地址

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

細說Nullable類型
Javascript 「繼承」
使用CoApp創建NuGet C++靜態庫包
大話Python正則表達式
Linux 最新SO_REUSEPORT特性

TAG:達人科技 |

您可能感興趣

TypeScript基礎之高級類型的可辨識聯合(Discriminated Unions)
python中list,array,mat,tuple大小及類型
Chrome 66 新特性:CSS 類型對象模型,非同步剪貼板 API,AudioWorklet,等
Hibernate 映射枚舉Enum 類型的屬性
SM、jyp、yg、cube、ymc等公司類型——其中big hit最霸氣
Google出品的Python代碼靜態類型分析器:Pytype
「Good idea/solution」 類型作文審題
python基礎之變數類型number(math模塊)
由光環新網運營的 AWS 中國區域現已推出 Amazon RDS for Oracle 支持 X1 實例類型
類型轉換運算符 運算符重載 operator new operator delete
「Python」Chapter1 變數和簡單數據類型
澳大利亞 Bunjil Place,高難度木曲線營造類型場所/fjmt
opencv Mat類型和BYTE*指針類型互轉
Pyright:微軟提供的Python靜態類型檢查器
鄭爽VS Angel baby 鹿晗VS易烊千璽,同類型綜藝
solidity之地址類型
Redis 數據類型
steam免費領取 HITMAN? 2 序章(FOD 類型)
Mariadb學習總結(三):數據類型
Summary 數據類型詳解