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