hibernate存取json數(shù)據(jù)的代碼分析
一、場(chǎng)景
public class OrderModel {
private List<String> favorableDescList;
}
訂單中會(huì)存儲(chǔ)一些優(yōu)惠信息,方便頁(yè)面展示時(shí)使用,如:
1、滿100減50
2、參與【老會(huì)員真情回饋——精品課程體驗(yàn)活動(dòng)】,僅需支付200.00學(xué)幣
3、【Oracle + PL/SQL 實(shí)戰(zhàn)】套裝課程的【搶購(gòu)】活動(dòng),優(yōu)惠120.00學(xué)幣
……等等
如圖所示,我們?cè)陧?yè)面給用戶展示他們參與的優(yōu)惠信息:

二、分析
如上優(yōu)惠信息有如下特點(diǎn):
1、只用于展示,不會(huì)涉及修改;
2、一旦訂單支付成功,不會(huì)再改變;
3、數(shù)據(jù)量不會(huì)很大。
三、解決方案
1、最簡(jiǎn)單的解決方案是關(guān)聯(lián)表:

但這種解決方案需要連表進(jìn)行查詢,感覺(jué)是沒(méi)有必要的,畢竟只是展示數(shù)據(jù),用關(guān)聯(lián)表有點(diǎn)殺雞用牛刀的感覺(jué)。
2、JSON解決方案:

通過(guò)如上思路我們可以解決許多類似的問(wèn)題。
3、代碼示例:
1、模型類:
Java代碼
public class OrderModel {
@Type(type = "com.bjpowernode.framework.hibernate.type.JsonType") //①
private List<String> favorableDescList;
}
①處使用我們自定義的Hibernate類型來(lái)進(jìn)行轉(zhuǎn)換,上邊代碼只有一部分
2、自定義JsonType
Java代碼
package com.bjpowernode.framework.hibernate.type;
//省略import
public class JsonType implements UserType, Serializable {
private String json;
@Override
public int[] sqlTypes() {
return new int[] {Hibernate.STRING.sqlType()};
}
@Override
public Class returnedClass() {
return JsonList.class;
}
@Override
public boolean equals(Object o, Object o1) throws HibernateException {
if (o == o1) {
return true;
}
if (o == null || o == null) {
return false;
}
return o.equals(o1);
}
@Override
public int hashCode(Object o) throws HibernateException {
return o.hashCode();
}
/**
* 從JDBC ResultSet讀取數(shù)據(jù),將其轉(zhuǎn)換為自定義類型后返回
* (此方法要求對(duì)克能出現(xiàn)null值進(jìn)行處理)
* names中包含了當(dāng)前自定義類型的映射字段名稱
* @param resultSet
* @param names
* @param owner
* @return
* @throws HibernateException
* @throws SQLException
*/
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
String json = resultSet.getString(names[0]);
if(json == null || json.trim().length() == 0) {
return new JsonList();
}
return JSONArray.toList(JSONArray.fromObject(json), JsonList.class);
}
/**
* 本方法將在Hibernate進(jìn)行數(shù)據(jù)保存時(shí)被調(diào)用
* 我們可以通過(guò)PreparedStateme將自定義數(shù)據(jù)寫入到對(duì)應(yīng)的數(shù)據(jù)庫(kù)表字段
* @param preparedStatement
* @param value
* @param i
* @throws HibernateException
* @throws SQLException
*/
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int i) throws HibernateException, SQLException {
if(value == null) {
preparedStatement.setNull(i, Hibernate.STRING.sqlType());
} else {
preparedStatement.setString(i, JSONArray.fromObject(value).toString());
}
}
/**
* 提供自定義類型的完全復(fù)制方法
* 本方法將用構(gòu)造返回對(duì)象
* 當(dāng)nullSafeGet方法調(diào)用之后,我們獲得了自定義數(shù)據(jù)對(duì)象,在向用戶返回自定義數(shù)據(jù)之前,
* deepCopy方法將被調(diào)用,它將根據(jù)自定義數(shù)據(jù)對(duì)象構(gòu)造一個(gè)完全拷貝,并將此拷貝返回給用戶
* 此時(shí)我們就得到了自定義數(shù)據(jù)對(duì)象的兩個(gè)版本,第一個(gè)是從數(shù)據(jù)庫(kù)讀出的原始版本,其二是我們通過(guò)
* deepCopy方法構(gòu)造的復(fù)制版本,原始的版本將有Hibernate維護(hù),復(fù)制版由用戶使用。原始版本用作
* 稍后的臟數(shù)據(jù)檢查依據(jù);Hibernate將在臟數(shù)據(jù)檢查過(guò)程中將兩個(gè)版本的數(shù)據(jù)進(jìn)行對(duì)比(通過(guò)調(diào)用
* equals方法),如果數(shù)據(jù)發(fā)生了變化(equals方法返回false),則執(zhí)行對(duì)應(yīng)的持久化操作
*
* @param o
* @return
* @throws HibernateException
*/
@Override
public Object deepCopy(Object o) throws HibernateException {
if(o == null) return null;
JsonList jsonList = new JsonList();
jsonList.addAll((List)o);
return jsonList;
}
/**
* 本類型實(shí)例是否可變
* @return
*/
@Override
public boolean isMutable() {
return true;
}
/* 序列化 */
@Override
public Serializable disassemble(Object value) throws HibernateException {
return ((Serializable)value);
}
/* 反序列化 */
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}
JSON框架使用的是json-lib 2.1。
3、自定義JsonList
Java代碼
package com.bjpowernode.framework.hibernate;
public class JsonList<T> extends ArrayList implements Cloneable {
}
就這么簡(jiǎn)單,歡迎大家討論。
有人說(shuō)有性能問(wèn)題,我寫了個(gè)測(cè)試用例:
測(cè)試機(jī)器:CPU:p8700(雙核@2.53GHZ) 內(nèi)存:2G
一、插入
1、JSON方式插入10w條
create 100000 elapsed time(millis):21031
2、關(guān)聯(lián)表插入10w條
create 100000 elapsed time(millis):79219
JSON性能遠(yuǎn)遠(yuǎn)好于關(guān)聯(lián)表,關(guān)聯(lián)表要插入兩個(gè)表。
二、查詢
1、JSON方式分頁(yè)(100條一頁(yè))查詢10w條
select 100000 elapsed time(millis):146047
2、關(guān)聯(lián)表分頁(yè)(100條一頁(yè))查詢10w條
select 100000 elapsed time(millis):275375
JSON性能遠(yuǎn)遠(yuǎn)好于關(guān)聯(lián)表,關(guān)聯(lián)表需要join連表查詢。
JSON方式的缺點(diǎn):分析統(tǒng)計(jì)等查詢是雞肋、大數(shù)據(jù)量是雞肋(一列存儲(chǔ)數(shù)據(jù)量不可能太大)。
我的應(yīng)用場(chǎng)景:優(yōu)惠信息、購(gòu)物車持久化(每個(gè)用戶購(gòu)物車最多50條)。
總結(jié)
以上所述是小編給大家介紹的hibernate存取json數(shù)據(jù)的代碼分析,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Mac系統(tǒng)搭建JDK及JMETER過(guò)程解析
這篇文章主要介紹了Mac系統(tǒng)搭建JDK及JMETER過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
Java跳過(guò)證書訪問(wèn)HTTPS詳細(xì)代碼示例
在訪問(wèn)HTTPS網(wǎng)站時(shí),Java會(huì)默認(rèn)檢查SSL證書是否有效,如果證書無(wú)效,則會(huì)阻止訪問(wèn),這篇文章主要給大家介紹了關(guān)于Java跳過(guò)證書訪問(wèn)HTTPS的相關(guān)資料,需要的朋友可以參考下2024-02-02
java 出現(xiàn)問(wèn)題javax.servlet.http.HttpServlet was not found解決方法
這篇文章主要介紹了java 出現(xiàn)問(wèn)題javax.servlet.http.HttpServlet was not found解決方法的相關(guān)資料,需要的朋友可以參考下2016-11-11
徹底搞懂java并發(fā)ThreadPoolExecutor使用
這篇文章主要為大家介紹了徹底搞懂java并發(fā)ThreadPoolExecutor使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Spring實(shí)戰(zhàn)之使用Resource作為屬性操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用Resource作為屬性,結(jié)合實(shí)例形式分析了spring載人Resource作為屬性相關(guān)配置與使用技巧,需要的朋友可以參考下2020-01-01
SpringBoot 過(guò)濾器與攔截器實(shí)例演示
本文通過(guò)示例代碼給大家講解SpringBoot 過(guò)濾器與攔截器的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2021-11-11
解析Java線程編程中的線程安全與synchronized的使用
這篇文章主要介紹了Java線程編程中的線程安全與synchronized的使用,synchronized多線程使用時(shí)一定要注意線程之間的沖突問(wèn)題,需要的朋友可以參考下2015-12-12

