一:字典表
字典信息:在項(xiàng)目中可能會(huì)使用到,已經(jīng)存在的一些信息。 例如,客戶的級(jí)別:普通用戶,vip用戶... 客戶的來(lái)源:網(wǎng)絡(luò)營(yíng)銷,電話營(yíng)銷... 客戶所屬行業(yè):電子商務(wù),房地產(chǎn)... 客戶的性別:男,女 在保存用戶的時(shí)候,這些信息都是已經(jīng)存在的,不應(yīng)該讓用戶讓用戶來(lái)任意填寫, 而是通過(guò)下拉列表來(lái)讓用戶選擇。 這些已經(jīng)存在的信息稱之為字典信息,將字典信息保存在字典表中。
二:表的設(shè)計(jì)
客戶表和級(jí)別表,來(lái)源表和所屬行業(yè)表的關(guān)系
客戶和級(jí)別表,行業(yè)表,來(lái)源表都屬于多對(duì)一的關(guān)系 為了簡(jiǎn)化開(kāi)發(fā),可以將三張字典數(shù)據(jù)合成一張字典表
字典表中的內(nèi)容
三:實(shí)體之間的設(shè)計(jì)
customer表中的cust_level,cust_source,cust_industry字段屬于外鍵 對(duì)應(yīng)著字典表basedict中的dict_id主鍵 在多方(客戶實(shí)體)中存在一方對(duì)象(字典實(shí)體)的引用 Customer實(shí)體設(shè)計(jì)
public class Customer implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long cust_id; private String cust_name; private String cust_phone; private String cust_mobile; //配置主外鍵關(guān)系 referencedColumnName外鍵所指向的主鍵 name:外鍵名稱 @ManyToOne(targetEntity=BaseDict.class) @JoinColumn(name="cust_level",referencedColumnName="dict_id") private BaseDict level; 客戶級(jí)別 @ManyToOne(targetEntity=BaseDict.class) @JoinColumn(name="cust_source",referencedColumnName="dict_id") private BaseDict source; 客戶來(lái)源 @ManyToOne(targetEntity=BaseDict.class) @JoinColumn(name="cust_industry",referencedColumnName="dict_id") private BaseDict industry; 客戶所屬行業(yè)
字典實(shí)體(BaseDict)
@Entity @Table(name="base_dict") public class BaseDict implements Serializable{ private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long dict_id; 字典表id private String dict_type_code; 類別(該條記錄是來(lái)源,行業(yè)還是級(jí)別的標(biāo)識(shí)) private String dict_type_name; 類別的名稱(客戶來(lái)源,客戶行業(yè),客戶級(jí)別) private String dict_item_name; 來(lái)源,級(jí)別,行業(yè)中的具體項(xiàng)(vip,房地產(chǎn),網(wǎng)絡(luò)營(yíng)銷) private String dict_item_code; private Integer dict_sort; 排序使用 private Character dict_enable; private String dict_memo;
知識(shí)回顧:Hibernate中查詢的api
①:oid 通過(guò)id查詢 get load方法 ②hql:在HQL語(yǔ)句中不可能出現(xiàn)于數(shù)據(jù)庫(kù)相關(guān)的信息,因?yàn)樗敲嫦驅(qū)ο髞?lái)操作的, 只會(huì)出現(xiàn)實(shí)體類中的屬性或?qū)ο笕绻霈F(xiàn)了表名或者表中的字段, 那么肯定是你的表名和類名相同,表中的字段和類中的屬性相同 查詢的api Query query = session.createQuery(hql語(yǔ)句); query.list()查詢所有 query.uniqueResult()返回單一值 基本查詢:from 類名 查詢?cè)搶?shí)體類映射的表中所有的記錄封裝為L(zhǎng)ist
hql查詢續(xù): 排序 String sql = "from Customer order by 屬性名 desc"; //desc降序 默認(rèn)為升序 聚合函數(shù) count|sum|max|min|avg select count(cust_id) from Customer count(*)也ok 投影查詢 查詢部分列 要求實(shí)體類必須要有select后面的構(gòu)造函數(shù) String hql = "select new Customer(c.cust_id,c.cust_name) from Customer c"; ③:qbc查詢 session.createCriteria(持久化類的字節(jié)碼對(duì)象) 分頁(yè): setFirstResult(int 開(kāi)啟的索引) setMaxResults(int 每頁(yè)顯示的條數(shù)) 排序: addOrder(Order.desc|asc(屬性名)); 統(tǒng)計(jì): setProjection(Projections.count|sum|min|max|avg(屬性名)) setProjection(Projections.rowCount()) 條件: add(Resitrctions.eq|like|gt|lt(屬性名稱,參數(shù)..));
離線查詢對(duì)象: DetachedCriteria:api和Criteria中完全相同 DetachedCriteria dc = DetachedCriteria(持久化類的字節(jié)碼對(duì)象); 在web層進(jìn)行使用,在條件查詢的時(shí)候?qū)Σ樵兊臈l件進(jìn)行封裝,在調(diào)用service層 方法得時(shí)候,只需要傳遞dc對(duì)象就ok。 HibernateTemplate(Hibernate模板操作數(shù)據(jù)庫(kù)) save(obj) update(obj) delete(obj) get(class,id) load(class,id) findByCriteria(DetachedCriteria dc):qbc查詢 findByCriteria(DetachedCriteria dc,int firstResult,int maxResults):qbc分頁(yè) find(String hql,Object... args):hql
需求一:添加客戶到數(shù)據(jù)庫(kù)中
添加客戶的頁(yè)面:
在添加用戶的時(shí)候,要先從數(shù)據(jù)庫(kù)中查詢出客戶級(jí)別,信息來(lái)源,所屬行業(yè) 這些字典信息來(lái)讓用戶進(jìn)行選擇 由兩種方式: ①:同步方式 先跳轉(zhuǎn)到action,將查詢到的字典內(nèi)容放置到值棧中,然后再請(qǐng)發(fā)到add.jsp ②:異步方式 直接到add.jsp頁(yè)面,當(dāng)頁(yè)面加載完成的時(shí)候發(fā)送ajax請(qǐng)求
先使用第一種方式:
//查詢字典數(shù)據(jù) public void getDictValue(){ 通過(guò)類別可以查詢到來(lái)源,級(jí)別,所屬行業(yè)下的所有數(shù)據(jù) levelList = customerService.findBaseDictByTypeCode("006"); sourceList = customerService.findBaseDictByTypeCode("002"); industryList = customerService.findBaseDictByTypeCode("001"); }
字典數(shù)據(jù)的集合設(shè)置為action的成員屬性,提供get方法就可以在jsp頁(yè)面中獲取
add.jsp頁(yè)面
使用ognl+struts2標(biāo)簽獲取致函中的數(shù)據(jù)(獲取客戶來(lái)源,所屬行業(yè)類似)客戶級(jí)別 :
customer表中的cust_level,cust_source,cust_industry字段屬于外鍵 對(duì)應(yīng)著字典表basedict中的dict_id主鍵 表單中 級(jí)別的name屬性為:level.dict_id 來(lái)源的name屬性為: source.dict_id 會(huì)使用屬性封裝的方式封裝到BaseDict level中的dict_id 在保存Customer的時(shí)候會(huì)將對(duì)應(yīng)的外鍵(cust_level,cust_source,cust_industry)保存
需求2:查詢客戶列表信息(分頁(yè)+條件查詢)
分頁(yè)使用的ObjectVlaue(PageBean)部分代碼 mysql分頁(yè) limit ?,? 后臺(tái)需要的條件:起始索引,一頁(yè)顯示的記錄數(shù) 前臺(tái)需要的數(shù)據(jù):當(dāng)前頁(yè)顯示的數(shù)據(jù),總頁(yè)數(shù),總的記錄數(shù) 前臺(tái)需要傳遞的數(shù)據(jù):當(dāng)前頁(yè)(沒(méi)有傳遞默認(rèn)為1)一頁(yè)顯示的記錄數(shù)(沒(méi)有傳遞,給出默認(rèn)值) 起始索引:(當(dāng)前頁(yè)-1)*一頁(yè)顯示的記錄數(shù) 總記錄數(shù):從數(shù)據(jù)庫(kù)中查詢而來(lái) 總頁(yè)數(shù):Math.ceil(1.0*總記錄數(shù)/總頁(yè)數(shù)) 當(dāng)前頁(yè)顯示的數(shù)據(jù):數(shù)據(jù)庫(kù)中查詢
public class PageBeanimplements Serializable { private static final long serialVersionUID = 1L; private Integer startIndex = 0; //起始索引 private Integer pageSize = 3; //一頁(yè)顯示的記錄數(shù) private Integer pageNumber = 1; //當(dāng)前頁(yè),由前端用戶傳遞,如果用戶沒(méi)有傳遞默認(rèn)顯示第一頁(yè)的數(shù)據(jù) private List result; //封裝查詢出來(lái)的某一頁(yè)的數(shù)據(jù) private Long totalRecord; //總記錄數(shù) 從數(shù)據(jù)庫(kù)中查詢而來(lái) //計(jì)算而來(lái) 總記錄數(shù)%一頁(yè)顯示的記錄==0?總記錄數(shù)/一頁(yè)顯示的記錄:總記錄數(shù)/一頁(yè)顯示的記錄+1 private Integer totalPage; //總頁(yè)數(shù) public Integer getTotalPage() { totalPage = (int) Math.ceil(1.0*totalRecord/pageSize); return totalPage; } //外界來(lái)獲取起始索引 在內(nèi)部進(jìn)行計(jì)算 public Integer getStartIndex() { startIndex = (pageNumber - 1) * pageSize; return startIndex; } public void setPageSize(Integer pageSize) { if(pageSize != null){ 如果前臺(tái)沒(méi)有傳遞,使用默認(rèn)值 this.pageSize = pageSize; }else{ this.pageSize = 3; } } public void setPageNumber(Integer pageNumber) { if(pageNumber != null){ this.pageNumber = pageNumber; }else{ 如果前臺(tái)沒(méi)有傳遞,使用默認(rèn)值 this.pageNumber = 1; } } }
條件查詢:在web層使用DetachedCriteria來(lái)封裝查詢的條件 web層action中的代碼 使用DetachedCriteria來(lái)封裝查詢的條件,使用pageBean來(lái)封裝當(dāng)前頁(yè)和一頁(yè)顯示的數(shù)據(jù) 調(diào)用service層方法的時(shí)候傳遞DetachedCriteria對(duì)象和pageBean對(duì)象
DetachedCriteria dc = DetachedCriteria.forClass(Customer.class); /* * dc.add(Restrictions(propertyName, value))查詢提交 propertyName:是屬性字段 value是條件對(duì)應(yīng)的值 * 然后再使用對(duì)象導(dǎo)航查詢?nèi)プ值浔碇胁樵償?shù)據(jù) */ if(customer.getCust_name() != null &&!customer.getCust_name().trim().equals("")){ dc.add(Restrictions.like("cust_name","%"+customer.getCust_name().trim()+"%")); } /* * 對(duì)查詢的條件進(jìn)行判斷和封裝 不需要對(duì)對(duì)象進(jìn)行非空判斷, 因?yàn)槭褂媚P头庋b實(shí)體的時(shí)候,實(shí)體必須手動(dòng)創(chuàng)建 * 如果下拉列表沒(méi)有沒(méi)有被選擇,select傳遞的value為-1 */ if(customer.getLevel() != null && customer.getLevel().getDict_id() != -1){ dc.add(Restrictions.eq("level", customer.getLevel())); } if(customer.getSource() != null && customer.getSource().getDict_id() != -1){ dc.add(Restrictions.eq("source", customer.getSource())); } if(customer.getIndustry() != null && customer.getIndustry().getDict_id() != -1){ dc.add(Restrictions.eq("industry", customer.getIndustry())); } //傳遞的參數(shù)為離線查詢對(duì)象(封裝條件)和分頁(yè)需要的pageBean pageBean = customerService.findList(dc,pageBean);
service層的代碼
public PageBean findList(DetachedCriteria dc,PageBean pageBean) { /* * 需要填充的數(shù)據(jù)為當(dāng)前頁(yè)顯示的數(shù)據(jù) * 總的記錄數(shù) */ //查詢總的記錄數(shù)(需要傳遞dc離線查詢對(duì)象,因?yàn)椴恢故欠猪?yè),是條件+分頁(yè)) Long totalRecord = customerDao.searchTotalRecord(dc); pageBean.setTotalRecord(totalRecord); //查詢當(dāng)前頁(yè)顯示的記錄 Listresult = customerDao.searchCustomerList(dc,pageBean); pageBean.setResult(result); return pageBean; }
dao層的代碼:
@Override public Long searchTotalRecord(DetachedCriteria dc) { //設(shè)置投影(聚合) dc.setProjection(Projections.rowCount()); /* * 查詢語(yǔ)句類似于 select count(*) from Customer * 如果有條件的分頁(yè)就是select count(*) from Customer where ...... */ Listrecord = (List ) hibernateTemplate.findByCriteria(dc); /* * 查詢完成之后需要去除投影,因?yàn)椴樵兺瓿煽傆涗洈?shù)之后 * 還需要查詢當(dāng)前頁(yè)顯示的數(shù)據(jù) 使用的是一個(gè)離線查詢對(duì)象 */ dc.setProjection(null); return record.get(0); } //分頁(yè)+條件查詢 查詢當(dāng)前頁(yè)顯示的數(shù)據(jù) @Override public List searchCustomerList(DetachedCriteria dc, PageBean pageBean) { List customerList = (List ) hibernateTemplate.findByCriteria(dc, pageBean.getStartIndex(), pageBean.getPageSize()); return customerList; }
要注意的就是在進(jìn)行總記錄數(shù)查詢的時(shí)候dc.setProjection(Projections.rowCount()); 當(dāng)查詢完成的時(shí)候去去除投影,因?yàn)榻酉聛?lái)查詢當(dāng)前頁(yè)顯示的記錄數(shù)使用的也是同一個(gè) 離線查詢對(duì)象。
查詢條件的回顯
兩種方式:
方式一:使用el表達(dá)式進(jìn)行判斷
方式二:使用jqery屬性選擇器 使用jquery的屬性選擇器來(lái)進(jìn)行判斷 當(dāng)下拉列表中option中的值與之前選擇的值相同時(shí),讓匹配的option選中
前臺(tái)頁(yè)面: 當(dāng)點(diǎn)擊下一頁(yè)或者索引頁(yè)的時(shí)候,使用的是超鏈接。 但是分頁(yè)+條件查詢,查詢的條件在表單中 解決:當(dāng)點(diǎn)擊索引頁(yè)。上一頁(yè)下一頁(yè)之后。 為超鏈接提供點(diǎn)擊事件: 將當(dāng)前點(diǎn)擊的頁(yè)數(shù)動(dòng)態(tài)的放置在表單輸入項(xiàng)中 然后提交表單,這樣會(huì)將查詢的條件和當(dāng)前頁(yè)一起提交到后臺(tái)頁(yè)面
當(dāng)前頁(yè)的表單 后一頁(yè) function toPage(pageNumber){ //獲取到提交當(dāng)前頁(yè)的輸入框 $("#pageNumberId").val(pageNumber); //提交表單 $("#customerForm").submit(); }
需求三:修改客戶信息: 先查詢后修改: 據(jù)客戶的id先查詢客戶信息,然后請(qǐng)求轉(zhuǎn)發(fā)到edit.jsp頁(yè)面顯示要修改的客戶信息 private Customer customer = new Customer(); //使用模型驅(qū)動(dòng)進(jìn)行表單數(shù)據(jù)的封裝 @Override public Customer getModel() { return customer; } 使用模型驅(qū)動(dòng)封裝要修改的的客戶id 此時(shí)customer中只有客戶的id 這時(shí)候如果還使用customer來(lái)接收的話,請(qǐng)求轉(zhuǎn)發(fā)到edit.jsp頁(yè)面中 通過(guò)${成員屬性}是獲取不到內(nèi)容的 因?yàn)閏ustomer引用重新指向了一個(gè)對(duì)象 要想在edit.jsp頁(yè)面中獲取到查詢到的內(nèi)容 有三種方式: 一:使用customer來(lái)接收 使用ActionContext.getContext.getValueStack().push(customer); 向root棧中存放customer指向的新對(duì)象 可以使用${成員屬性獲取到新內(nèi)容} 二:創(chuàng)建一個(gè)新的Customer findCustomer對(duì)象來(lái)接收,為該customer也提供相應(yīng)的get方法 在頁(yè)面就可以使用${findCustomer.成員屬性}來(lái)獲取導(dǎo)內(nèi)容 三:使用模型封裝的customer來(lái)接收 在edit.jsp頁(yè)面就可以使用${model.成員屬性}的方法來(lái)獲取到內(nèi)容
no-session問(wèn)題: could not initialize proxy - no Session 原因:懶加載的問(wèn)題 使用id獲取要修改的對(duì)象時(shí),使用load方法 訪問(wèn) service 訪問(wèn)dao 返回是linkman的代理對(duì)象 代理對(duì)象返回給web層 頁(yè)面獲取數(shù)據(jù) 代理對(duì)象在使用時(shí)才會(huì)真正的去查詢 但是session已經(jīng)關(guān)閉
no-session的解決方案:
1、立即查詢 2、延長(zhǎng)session的存活時(shí)間 在web層將代理對(duì)象的數(shù)據(jù)查詢完畢后在讓session關(guān)閉 spring提供了一個(gè)Filter ----- OpenSessionInViewOpenSessionInViewFilter org.springframework.orm.hibernate5.support.OpenSessionInViewFilter 注意一:必須讓該過(guò)濾器在Struts2核心過(guò)濾器之前執(zhí)行 因?yàn)楫?dāng)Struts核心過(guò)濾器執(zhí)行完成之后,action的方法已經(jīng)被執(zhí)行 在操作數(shù)據(jù)庫(kù)的時(shí)候session對(duì)象還沒(méi)有創(chuàng)建,還是會(huì)有no-session問(wèn)題 注意二:OpenSessionInViewFilter hibernate5.support.OpenSessionInViewFilter 必須和你導(dǎo)入Hibernate的版本一致,在這里是Hibernate5版本 否則可能會(huì)有異常: org.hibernate.SessionFactory.openSession()Lorg/hibernate/classic/Session OpenSessionInViewFilter /*
no-session:懶加載問(wèn)題
原生hibernate(非jpa形式) 類級(jí)別的延遲 load() 直接查詢實(shí)體對(duì)象時(shí)是否延遲 配置默認(rèn)true 關(guān)聯(lián)級(jí)別的延遲 關(guān)聯(lián)類的延遲 linkman關(guān)聯(lián)customer ----默認(rèn)proxy 關(guān)聯(lián)集合的延遲 customer關(guān)聯(lián)linkman ---默認(rèn)是true
jpa形式的hibernate 一對(duì)多 查詢一的一方多 多的一方默認(rèn)延遲加載 查詢customer 對(duì)應(yīng)的linkman 延遲加載 多對(duì)一 查詢多的一方 一的一方默認(rèn)立即加載 查詢linkman 對(duì)應(yīng)的customer的立即加載
刪除客戶(一方)刪除客戶的時(shí)候要?jiǎng)h除客戶下對(duì)應(yīng)的聯(lián)系人,配置級(jí)聯(lián)刪除 cascade=CascadeType.REMOVE 一方放棄維護(hù)關(guān)系,所以不能直接刪除,需要先查后刪 //在刪除一方的時(shí)候先查詢后刪除,因?yàn)椴樵兂鰜?lái)的對(duì)象和多表的一方存在關(guān)系,可以級(jí)聯(lián)刪除 customer = hibernateTemplate.get(Customer.class, customer.getCust_id()); hibernateTemplate.delete(customer); 刪除多方的時(shí)候可以直接刪除,單表操作的時(shí)候可以直接刪除
ajax的遞歸錯(cuò)誤 There is a cycle in the hierarchy 在json格式轉(zhuǎn)換的時(shí)候出現(xiàn)死循環(huán) 表之間存在關(guān)系,Customer和LinkMan表是一對(duì)多的關(guān)系 在打印customer對(duì)象的時(shí)候,由于customer中存在LinkMan 會(huì)打印LinkMan對(duì)象,在打印LinkMan對(duì)象中,又存在Customer對(duì)象 遞歸調(diào)用,導(dǎo)致內(nèi)存溢出 需求: 添加聯(lián)系人的時(shí)候要選擇所屬客戶 在add.jsp頁(yè)面加載完成的時(shí)候,發(fā)送ajax請(qǐng)求 獲取數(shù)據(jù)庫(kù)中的所有客戶信息
web層的代碼:
//去數(shù)據(jù)庫(kù)中查找所有的客戶信息 @Action("customer_findCustomerList") public void findCustomerList() throws IOException{ ListcustomerList = customerService.findAll(); //發(fā)送的是ajax請(qǐng)求 轉(zhuǎn)換為json格式的數(shù)據(jù) JsonConfig jsonConfig = new JsonConfig(); 設(shè)置不參與轉(zhuǎn)換的字段 jsonConfig.setExcludes(new String[]{"linkMen"}); String json = JSONArray.fromObject(customerList,jsonConfig).toString(); //將json格式的數(shù)據(jù)寫會(huì)給瀏覽器,解決中文亂碼問(wèn)題 HttpServletResponse response = ServletActionContext.getResponse(); response.setCharacterEncoding("UTF-8"); response.getWriter().println(json); }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/84773.html
一:字典表 字典信息:在項(xiàng)目中可能會(huì)使用到,已經(jīng)存在的一些信息。 例如,客戶的級(jí)別:普通用戶,vip用戶... 客戶的來(lái)源:網(wǎng)絡(luò)營(yíng)銷,電話營(yíng)銷... 客戶所屬行業(yè):電子商務(wù),房地產(chǎn)... 客戶的性別:男,女 在保存用戶的時(shí)候,這些信息都是已經(jīng)存在的,不應(yīng)該讓用戶讓用戶來(lái)任意填寫, 而是通過(guò)下拉列表來(lái)讓用戶選擇。 這些已經(jīng)存在的信息稱之為字典信...
摘要:前言由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 前言 由于寫的文章已經(jīng)是有點(diǎn)多了,為了自己和大家的檢索方便,于是我就做了這么一個(gè)博客導(dǎo)航。 由于更新比較頻繁,因此隔一段時(shí)間才會(huì)更新目錄導(dǎo)航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號(hào):Java3y Java3y文章目錄導(dǎo)航 Java基礎(chǔ) 泛型就這么簡(jiǎn)單 注解就這么簡(jiǎn)單 Druid數(shù)據(jù)庫(kù)連接池...
摘要:需求整合框架做一個(gè)保存用戶的業(yè)務(wù),業(yè)務(wù)比較簡(jiǎn)單,重在框架整合。 需求:整合ssh框架做一個(gè)保存用戶的業(yè)務(wù),業(yè)務(wù)比較簡(jiǎn)單,重在ssh框架整合。創(chuàng)建數(shù)據(jù)庫(kù)和表 CREATE DATABASE ssh01; USE DATABASE; 表由Hibernate創(chuàng)建,可以看配置是否成功 一:導(dǎo)入jar包 Hibernate需要jar Hibernate基本jar mysql驅(qū)動(dòng) ...
摘要:在結(jié)構(gòu)上引入了頭結(jié)點(diǎn)和尾節(jié)點(diǎn),他們分別指向隊(duì)列的頭和尾,嘗試獲取鎖入隊(duì)服務(wù)教程在它提出十多年后的今天,已經(jīng)成為最重要的應(yīng)用技術(shù)之一。隨著編程經(jīng)驗(yàn)的日積月累,越來(lái)越感覺(jué)到了解虛擬機(jī)相關(guān)要領(lǐng)的重要性。 JVM 源碼分析之 Jstat 工具原理完全解讀 http://click.aliyun.com/m/8315/ JVM 源碼分析之 Jstat 工具原理完全解讀 http:...
閱讀 3076·2021-11-24 11:14
閱讀 3514·2021-11-22 15:22
閱讀 3210·2021-09-27 13:36
閱讀 720·2021-08-31 14:29
閱讀 1334·2019-08-30 15:55
閱讀 1765·2019-08-29 17:29
閱讀 1151·2019-08-29 16:24
閱讀 2412·2019-08-26 13:48