成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

ssh框架整合案例(字典表,no-session,hebiernate|模板的api,懶加載,級聯(lián)刪

lufficc / 3089人閱讀

一:字典表

字典信息:在項目中可能會使用到,已經(jīng)存在的一些信息。
    例如,客戶的級別:普通用戶,vip用戶...
    客戶的來源:網(wǎng)絡(luò)營銷,電話營銷...
    客戶所屬行業(yè):電子商務(wù),房地產(chǎn)...
    客戶的性別:男,女
    在保存用戶的時候,這些信息都是已經(jīng)存在的,不應(yīng)該讓用戶讓用戶來任意填寫,
    而是通過下拉列表來讓用戶選擇。
    這些已經(jīng)存在的信息稱之為字典信息,將字典信息保存在字典表中。

二:表的設(shè)計

客戶表和級別表,來源表和所屬行業(yè)表的關(guān)系

客戶和級別表,行業(yè)表,來源表都屬于多對一的關(guān)系
為了簡化開發(fā),可以將三張字典數(shù)據(jù)合成一張字典表

字典表中的內(nèi)容

三:實體之間的設(shè)計

customer表中的cust_level,cust_source,cust_industry字段屬于外鍵
對應(yīng)著字典表basedict中的dict_id主鍵
在多方(客戶實體)中存在一方對象(字典實體)的引用
Customer實體設(shè)計
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;    客戶級別
    @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; 客戶所屬行業(yè)

字典實體(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;   類別(該條記錄是來源,行業(yè)還是級別的標識)
    private String dict_type_name;   類別的名稱(客戶來源,客戶行業(yè),客戶級別)
    private String dict_item_name;   來源,級別,行業(yè)中的具體項(vip,房地產(chǎn),網(wǎng)絡(luò)營銷)
    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語句中不可能出現(xiàn)于數(shù)據(jù)庫相關(guān)的信息,因為它是面向?qū)ο髞聿僮鞯模?    只會出現(xiàn)實體類中的屬性或?qū)ο笕绻霈F(xiàn)了表名或者表中的字段,
    那么肯定是你的表名和類名相同,表中的字段和類中的屬性相同
    查詢的api
        Query query = session.createQuery(hql語句);
        query.list()查詢所有
        query.uniqueResult()返回單一值
    
    基本查詢:from 類名 查詢該實體類映射的表中所有的記錄封裝為List
    條件查詢:
        from 類名 where 屬性名 like ?         占位符
        from 類名 where 屬性名 = ? 
        from 類名 where 屬性名 like :name;    名稱占位符
        設(shè)置查詢條件:
            query.setParameter(0, "%o%");//設(shè)置?占位符的參數(shù)值   
            query.setParameter(name, "%o%");//設(shè)置命名占位符的參數(shù)值
     分頁查詢
         String sql = "from Customer";
         Query query = session.createQuery(sql);
         query.setFirstResult(0);//相當于設(shè)置limit的第一個參數(shù),起始索引
         query.setMaxResults(3);//相當于設(shè)置limit的第二個參數(shù),一頁顯示多少條記錄



hql查詢續(xù):
    排序
         String sql = "from Customer order by 屬性名 desc";  
        //desc降序  默認為升序 
    聚合函數(shù)  count|sum|max|min|avg
        select count(cust_id) from Customer
        count(*)也ok
    投影查詢 查詢部分列
        要求實體類必須要有select后面的構(gòu)造函數(shù)
        String hql = "select new Customer(c.cust_id,c.cust_name) from Customer c";

③:qbc查詢
    session.createCriteria(持久化類的字節(jié)碼對象)
    分頁:
        setFirstResult(int 開啟的索引)
        setMaxResults(int 每頁顯示的條數(shù))
    排序:
        addOrder(Order.desc|asc(屬性名));
    統(tǒng)計:
        setProjection(Projections.count|sum|min|max|avg(屬性名))
        setProjection(Projections.rowCount())
    條件:
        add(Resitrctions.eq|like|gt|lt(屬性名稱,參數(shù)..));
離線查詢對象:
    DetachedCriteria:api和Criteria中完全相同
    DetachedCriteria dc = DetachedCriteria(持久化類的字節(jié)碼對象);
    在web層進行使用,在條件查詢的時候?qū)Σ樵兊臈l件進行封裝,在調(diào)用service層
    方法得時候,只需要傳遞dc對象就ok。
HibernateTemplate(Hibernate模板操作數(shù)據(jù)庫)
    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
    

需求一:添加客戶到數(shù)據(jù)庫中

添加客戶的頁面:

    在添加用戶的時候,要先從數(shù)據(jù)庫中查詢出客戶級別,信息來源,所屬行業(yè)
這些字典信息來讓用戶進行選擇
由兩種方式:
①:同步方式    先跳轉(zhuǎn)到action,將查詢到的字典內(nèi)容放置到值棧中,然后再請發(fā)到add.jsp
②:異步方式    直接到add.jsp頁面,當頁面加載完成的時候發(fā)送ajax請求

先使用第一種方式:

//查詢字典數(shù)據(jù)
    public void getDictValue(){
        通過類別可以查詢到來源,級別,所屬行業(yè)下的所有數(shù)據(jù)
        levelList = customerService.findBaseDictByTypeCode("006");
        sourceList = customerService.findBaseDictByTypeCode("002");
        industryList = customerService.findBaseDictByTypeCode("001");
    }
字典數(shù)據(jù)的集合設(shè)置為action的成員屬性,提供get方法就可以在jsp頁面中獲取

add.jsp頁面

    使用ognl+struts2標簽獲取致函中的數(shù)據(jù)(獲取客戶來源,所屬行業(yè)類似)
    客戶級別 :
    
        
    
customer表中的cust_level,cust_source,cust_industry字段屬于外鍵
對應(yīng)著字典表basedict中的dict_id主鍵
表單中
級別的name屬性為:level.dict_id
來源的name屬性為: source.dict_id
會使用屬性封裝的方式封裝到BaseDict level中的dict_id
在保存Customer的時候會將對應(yīng)的外鍵(cust_level,cust_source,cust_industry)保存
需求2:查詢客戶列表信息(分頁+條件查詢)

分頁使用的ObjectVlaue(PageBean)部分代碼
mysql分頁    limit ?,?
    后臺需要的條件:起始索引,一頁顯示的記錄數(shù)
    前臺需要的數(shù)據(jù):當前頁顯示的數(shù)據(jù),總頁數(shù),總的記錄數(shù)
    前臺需要傳遞的數(shù)據(jù):當前頁(沒有傳遞默認為1)一頁顯示的記錄數(shù)(沒有傳遞,給出默認值)
    
    起始索引:(當前頁-1)*一頁顯示的記錄數(shù)
    總記錄數(shù):從數(shù)據(jù)庫中查詢而來
    總頁數(shù):Math.ceil(1.0*總記錄數(shù)/總頁數(shù))
    當前頁顯示的數(shù)據(jù):數(shù)據(jù)庫中查詢
public class PageBean implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer startIndex = 0;        //起始索引
    private Integer pageSize = 3;        //一頁顯示的記錄數(shù)
    private Integer pageNumber = 1;        //當前頁,由前端用戶傳遞,如果用戶沒有傳遞默認顯示第一頁的數(shù)據(jù)
    private List result;    //封裝查詢出來的某一頁的數(shù)據(jù)
    private Long totalRecord;        //總記錄數(shù)        從數(shù)據(jù)庫中查詢而來
    //計算而來    總記錄數(shù)%一頁顯示的記錄==0?總記錄數(shù)/一頁顯示的記錄:總記錄數(shù)/一頁顯示的記錄+1
    private Integer totalPage;            //總頁數(shù)        
    public Integer getTotalPage() {
        totalPage = (int) Math.ceil(1.0*totalRecord/pageSize);
        return totalPage;
    }
    
    //外界來獲取起始索引   在內(nèi)部進行計算
    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來封裝當前頁和一頁顯示的數(shù)據(jù)
調(diào)用service層方法的時候傳遞DetachedCriteria對象和pageBean對象
  DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);
 /*
    * dc.add(Restrictions(propertyName, value))查詢提交 
    propertyName:是屬性字段 value是條件對應(yīng)的值
    * 然后再使用對象導航查詢?nèi)プ值浔碇胁樵償?shù)據(jù)
*/
 if(customer.getCust_name() != null &&!customer.getCust_name().trim().equals("")){
    dc.add(Restrictions.like("cust_name","%"+customer.getCust_name().trim()+"%"));
 }
 /*
    * 對查詢的條件進行判斷和封裝 不需要對對象進行非空判斷,
    因為使用模型封裝實體的時候,實體必須手動創(chuàng)建
    * 如果下拉列表沒有沒有被選擇,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ù)為離線查詢對象(封裝條件)和分頁需要的pageBean
 pageBean = customerService.findList(dc,pageBean); 

service層的代碼

    public PageBean findList(DetachedCriteria dc,PageBean pageBean) {
        /*
         * 需要填充的數(shù)據(jù)為當前頁顯示的數(shù)據(jù)
         * 總的記錄數(shù)
         */
        //查詢總的記錄數(shù)(需要傳遞dc離線查詢對象,因為不止是分頁,是條件+分頁)
        Long totalRecord = customerDao.searchTotalRecord(dc);
        pageBean.setTotalRecord(totalRecord);
        //查詢當前頁顯示的記錄
        List result = customerDao.searchCustomerList(dc,pageBean);
        pageBean.setResult(result);
        return pageBean;
    }
dao層的代碼:
    @Override
    public Long searchTotalRecord(DetachedCriteria dc) {
        //設(shè)置投影(聚合)
        dc.setProjection(Projections.rowCount());
        /*
         * 查詢語句類似于 select count(*) from Customer 
         * 如果有條件的分頁就是select count(*) from Customer where ......
         */
        List record = (List) hibernateTemplate.findByCriteria(dc);
        /*
         * 查詢完成之后需要去除投影,因為查詢完成總記錄數(shù)之后
         * 還需要查詢當前頁顯示的數(shù)據(jù)  使用的是一個離線查詢對象
         */
        dc.setProjection(null);
        return record.get(0);
    }
    //分頁+條件查詢    查詢當前頁顯示的數(shù)據(jù)
    @Override
    public List searchCustomerList(DetachedCriteria dc, PageBean pageBean) {
        List customerList = (List) hibernateTemplate.findByCriteria(dc, pageBean.getStartIndex(), pageBean.getPageSize()); 
        return customerList;
    }
要注意的就是在進行總記錄數(shù)查詢的時候dc.setProjection(Projections.rowCount());
當查詢完成的時候去去除投影,因為接下來查詢當前頁顯示的記錄數(shù)使用的也是同一個
離線查詢對象。

查詢條件的回顯

兩種方式:
    方式一:使用el表達式進行判斷
    
方式二:使用jqery屬性選擇器
使用jquery的屬性選擇器來進行判斷

當下拉列表中option中的值與之前選擇的值相同時,讓匹配的option選中

前臺頁面:
    當點擊下一頁或者索引頁的時候,使用的是超鏈接。
    但是分頁+條件查詢,查詢的條件在表單中
    解決:當點擊索引頁。上一頁下一頁之后。
        為超鏈接提供點擊事件:
        將當前點擊的頁數(shù)動態(tài)的放置在表單輸入項中
        然后提交表單,這樣會將查詢的條件和當前頁一起提交到后臺頁面
  
當前頁的表單
    
    后一頁
    function toPage(pageNumber){
            //獲取到提交當前頁的輸入框
            $("#pageNumberId").val(pageNumber);
            //提交表單
            $("#customerForm").submit();
    }
需求三:修改客戶信息:
    先查詢后修改:
    據(jù)客戶的id先查詢客戶信息,然后請求轉(zhuǎn)發(fā)到edit.jsp頁面顯示要修改的客戶信息
    private Customer customer = new Customer();
    //使用模型驅(qū)動進行表單數(shù)據(jù)的封裝
    @Override
    public Customer getModel() {
        return customer;
    }
    使用模型驅(qū)動封裝要修改的的客戶id
    此時customer中只有客戶的id
    這時候如果還使用customer來接收的話,請求轉(zhuǎn)發(fā)到edit.jsp頁面中
    通過${成員屬性}是獲取不到內(nèi)容的
    因為customer引用重新指向了一個對象
    
    要想在edit.jsp頁面中獲取到查詢到的內(nèi)容
     有三種方式:
    一:使用customer來接收
        使用ActionContext.getContext.getValueStack().push(customer);
        向root棧中存放customer指向的新對象    可以使用${成員屬性獲取到新內(nèi)容}
    二:創(chuàng)建一個新的Customer findCustomer對象來接收,為該customer也提供相應(yīng)的get方法
        在頁面就可以使用${findCustomer.成員屬性}來獲取導內(nèi)容
    三:使用模型封裝的customer來接收
        在edit.jsp頁面就可以使用${model.成員屬性}的方法來獲取到內(nèi)容
        
no-session問題:
could not initialize proxy - no Session

原因:懶加載的問題
使用id獲取要修改的對象時,使用load方法
訪問 service 訪問dao 返回是linkman的代理對象
代理對象返回給web層
頁面獲取數(shù)據(jù) 代理對象在使用時才會真正的去查詢 但是session已經(jīng)關(guān)閉
no-session的解決方案:
1、立即查詢
2、延長session的存活時間 在web層將代理對象的數(shù)據(jù)查詢完畢后在讓session關(guān)閉
spring提供了一個Filter ----- OpenSessionInView


    OpenSessionInViewFilter
    org.springframework.orm.hibernate5.support.OpenSessionInViewFilter


    OpenSessionInViewFilter
    /*

注意一:必須讓該過濾器在Struts2核心過濾器之前執(zhí)行
因為當Struts核心過濾器執(zhí)行完成之后,action的方法已經(jīng)被執(zhí)行
在操作數(shù)據(jù)庫的時候session對象還沒有創(chuàng)建,還是會有no-session問題
注意二:OpenSessionInViewFilter    
hibernate5.support.OpenSessionInViewFilter
必須和你導入Hibernate的版本一致,在這里是Hibernate5版本
否則可能會有異常:
org.hibernate.SessionFactory.openSession()Lorg/hibernate/classic/Session

no-session:懶加載問題

原生hibernate(非jpa形式)
類級別的延遲
    load()  直接查詢實體對象時是否延遲  
    配置        默認true
    關(guān)聯(lián)級別的延遲
    關(guān)聯(lián)類的延遲
        linkman關(guān)聯(lián)customer
                ----默認proxy
        
    關(guān)聯(lián)集合的延遲
        customer關(guān)聯(lián)linkman
                    ---默認是true
jpa形式的hibernate

一對多 查詢一的一方多 多的一方默認延遲加載
    查詢customer 對應(yīng)的linkman 延遲加載
多對一 查詢多的一方 一的一方默認立即加載    
    查詢linkman  對應(yīng)的customer的立即加載
刪除客戶(一方)刪除客戶的時候要刪除客戶下對應(yīng)的聯(lián)系人,配置級聯(lián)刪除
cascade=CascadeType.REMOVE
一方放棄維護關(guān)系,所以不能直接刪除,需要先查后刪
//在刪除一方的時候先查詢后刪除,因為查詢出來的對象和多表的一方存在關(guān)系,可以級聯(lián)刪除
customer = hibernateTemplate.get(Customer.class, customer.getCust_id());
hibernateTemplate.delete(customer);

刪除多方的時候可以直接刪除,單表操作的時候可以直接刪除
ajax的遞歸錯誤
There is a cycle in the hierarchy
在json格式轉(zhuǎn)換的時候出現(xiàn)死循環(huán)
表之間存在關(guān)系,Customer和LinkMan表是一對多的關(guān)系
在打印customer對象的時候,由于customer中存在LinkMan
會打印LinkMan對象,在打印LinkMan對象中,又存在Customer對象
遞歸調(diào)用,導致內(nèi)存溢出
需求:
    添加聯(lián)系人的時候要選擇所屬客戶
    在add.jsp頁面加載完成的時候,發(fā)送ajax請求
    獲取數(shù)據(jù)庫中的所有客戶信息
    
web層的代碼:
//去數(shù)據(jù)庫中查找所有的客戶信息
    @Action("customer_findCustomerList")
    public void findCustomerList() throws IOException{
        List customerList = customerService.findAll();
        //發(fā)送的是ajax請求  轉(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ù)寫會給瀏覽器,解決中文亂碼問題
        HttpServletResponse response = ServletActionContext.getResponse();
        response.setCharacterEncoding("UTF-8");
        response.getWriter().println(json);
    }

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/84773.html

相關(guān)文章

  • ssh框架整合案例(字典,no-session,hebiernate|模板api,加載,聯(lián)刪

    一:字典表 字典信息:在項目中可能會使用到,已經(jīng)存在的一些信息。 例如,客戶的級別:普通用戶,vip用戶... 客戶的來源:網(wǎng)絡(luò)營銷,電話營銷... 客戶所屬行業(yè):電子商務(wù),房地產(chǎn)... 客戶的性別:男,女 在保存用戶的時候,這些信息都是已經(jīng)存在的,不應(yīng)該讓用戶讓用戶來任意填寫, 而是通過下拉列表來讓用戶選擇。 這些已經(jīng)存在的信息稱之為字典信...

    dkzwm 評論0 收藏0
  • Java3y文章目錄導航

    摘要:前言由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 前言 由于寫的文章已經(jīng)是有點多了,為了自己和大家的檢索方便,于是我就做了這么一個博客導航。 由于更新比較頻繁,因此隔一段時間才會更新目錄導航哦~想要獲取最新原創(chuàng)的技術(shù)文章歡迎關(guān)注我的公眾號:Java3y Java3y文章目錄導航 Java基礎(chǔ) 泛型就這么簡單 注解就這么簡單 Druid數(shù)據(jù)庫連接池...

    KevinYan 評論0 收藏0
  • ssh(Spring+Struts2+hibernate)整合

    摘要:需求整合框架做一個保存用戶的業(yè)務(wù),業(yè)務(wù)比較簡單,重在框架整合。 需求:整合ssh框架做一個保存用戶的業(yè)務(wù),業(yè)務(wù)比較簡單,重在ssh框架整合。創(chuàng)建數(shù)據(jù)庫和表 CREATE DATABASE ssh01; USE DATABASE; 表由Hibernate創(chuàng)建,可以看配置是否成功 一:導入jar包 Hibernate需要jar Hibernate基本jar mysql驅(qū)動 ...

    tulayang 評論0 收藏0
  • 后端經(jīng)驗

    摘要:在結(jié)構(gòu)上引入了頭結(jié)點和尾節(jié)點,他們分別指向隊列的頭和尾,嘗試獲取鎖入隊服務(wù)教程在它提出十多年后的今天,已經(jīng)成為最重要的應(yīng)用技術(shù)之一。隨著編程經(jīng)驗的日積月累,越來越感覺到了解虛擬機相關(guān)要領(lǐng)的重要性。 JVM 源碼分析之 Jstat 工具原理完全解讀 http://click.aliyun.com/m/8315/ JVM 源碼分析之 Jstat 工具原理完全解讀 http:...

    i_garfileo 評論0 收藏0

發(fā)表評論

0條評論

lufficc

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<