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-08Java跳過(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-02java 出現(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-02Spring實(shí)戰(zhàn)之使用Resource作為屬性操作示例
這篇文章主要介紹了Spring實(shí)戰(zhàn)之使用Resource作為屬性,結(jié)合實(shí)例形式分析了spring載人Resource作為屬性相關(guān)配置與使用技巧,需要的朋友可以參考下2020-01-01SpringBoot 過(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