關於Hibernate編程的特點與思考

來源:互聯網
上載者:User
編程

  Hibernate的一些弱點:比如對象關係的映射配置過多,控制複雜;交易處理面臨各種相容問題;HQL語言增加學習成本等。並提出了一些減化和退化方案,具體請看下面的原文,你的建議又如何?

  想了很長時間hibernate的一些弱點

  1.對象與資料庫的映射,關鍵在於對象關係的映射,但是沒做到很理想,配置過多,控制複雜,另外還會出錯。其實本質在於對象不夠自由。

  2.交易處理。這點上更容易出問題,相對於各種各樣的交易管理員,要相容是一個大問題,總歸在各種應用伺服器上有很多問題。其本質在於建立了一個自我資料存取小環境,必然面臨各種相容問題。

  3.HQL語言。建立物件查詢語言,類SQL,但是不同於任何一種SQL,調試環境複雜。本質在於建立了一種語言,增加學習成本。

  減化hibernate,將其退化成一個sql產生器,既可以保留原有的主要功能,又可以相容各種應用伺服器和資料庫伺服器,另外還不需要學習HQL語言。

  只需要一系列的功能函數,作一下封裝,再根據不同資料庫產生不同的SQL即可,連資料庫類型都不用指定,因為從Connection中可以獲得資料庫類型屬性。

  假想中的API:

  public Object ResultMapObject(ResultSet rs,String xml) //一行映射單個對象,可以用XML綁定,也可以不用。

  public List SQLMapObjects(Connection conn,String []sqls,String xml)  //將一堆SQL映射成一個對象樹,可以用xml來描述綁定,也可以不用,僅使用ror方式的約定。

  藉助JDBC和SQL可以構建整個資料存取層。

  映射單個對象的代碼,將一行記錄映射成單個對象。sql可以是任意的。

    Connection conn=DriverManager.getConnection(url);
    PreparedStatement ps = conn.prepareStatement(sql);
    
    ResultSet rs = ps.executeQuery();
    while(rs.next())
    {
      user=(Users)ResultMapObject(rs);
      //TODO 可以使用user
    }

  映射對象樹。

    /*
    sale_orders銷售訂單表
    sale_order_details銷售訂單細表
    products商品表
    product_catalogs商品類別表
    從sql中就可以分析出
    id是主鍵
    sale_order_details.sale_order_id===>sale_orders.id
    sale_order_details.product_catalog_id==>product_catalogs.id
    sale_order_details.product_id==>products.id
     */
    String []sqls=new String []{
        " select id, total_sum, memo, state, modify_date, creator, checker from sale_orders ",
        " select id, sale_order_id, product_id, product_name, product_catalog_id, model, product_unit, product_amount, product_price, product_sum, memo from sale_order_details ",
        " select id, name, catalog, model, price, unit, memo, createtime, state, code, productno from products ",
        " select id, name, memo from product_catalogs"
    };
    //不帶XML映射的,但是無法得知一對一還是一對多還是多對多的關係,所以一律建成多對多關係。
    List l=SQLMapObjects(conn,sqls);
    /*
    l的結構:
    sale_orders[]
        |-----sale_order_details[](sale_order_details.sale_order_id===>sale_orders.id)
                |-----products[](sale_order_details.product_id==>products.id)
                |-----product_catalogs[](sale_order_details.product_catalog_id==>product_catalogs.id)                
     */
  /*帶xml */

    /*
    sale_orders銷售訂單表
    sale_order_details銷售訂單細表
    products商品表
    product_catalogs商品類別表
    從sql中就可以分析出
    id是主鍵
    sale_order_details.sale_order_id===>sale_orders.id
    sale_order_details.product_catalog_id==>product_catalogs.id
    sale_order_details.product_id==>products.id
     */
    String []sqls=new String []{
        " select id, total_sum, memo, state, modify_date, creator, checker from sale_orders ",
        " select id, sale_order_id, product_id, product_name, product_catalog_id, model, product_unit, product_amount, product_price, product_sum, memo from sale_order_details ",
        " select id, name, catalog, model, price, unit, memo, createtime, state, code, productno from products ",
        " select id, name, memo from product_catalogs"
    };

    /*



    
        
        
            id
            id
        
        
        可選...
    
    
        
        
            product_id
            id
        
        可選...
    
    
        
            product_catalog_id
            id
        
        可選...
    
    
        可選...
    

     */

    String xml="...";
    //帶xml映射
    List l=SQLMapObjects(conn,sqls,xml);
    /*
    l的結構:
    sale_orders[]
        |-----sale_order_details[](sale_order_details.sale_order_id===>sale_orders.id)
                |-----products[](sale_order_details.product_id==>products.id)
                |-----product_catalogs[](sale_order_details.product_catalog_id==>product_catalogs.id)                
     */

  當然類要事先寫好,這裡就不詳細寫了。

  儲存問題更嚴重,取出來用sql映射已經可以很好地解決了,基本上一個函數、一群SQL,加上少少的XML就可以表達清楚了,但是這不能解決儲存對象的問題。

  假想中的儲存API.

  public void saveObject(Connection conn, Object obj,String xml);  //儲存單個對象,簡單地將對象擴充成sql,允許xml映射,也可以不映射

  public void saveObjects(Connection conn, List objs, String xml);  //將對象樹儲存到資料庫

  上一篇取出的List或人工組合的List可以用saveObjects來儲存,這個函數的任務就比較重了,因為沒有狀態,所以要判斷修改過非常麻煩。

  一種思路是在對象是增加屬性,然後由開發人員維護,比如介面上是否修改很有可能是有狀態位的,這個狀態位就可以用起來,然後函數根據這個狀態位來判斷是否去更新。

  一種思路是從Class本身中就得知對象是否被改過,類似AOP,在修改的時候記錄一下,然後函數來判斷是否改過,然後組成SQL來更新。

  至於批量修改是強項,直接用SQL即可,學習SQL比HQL的成本要低,畢竟這麼多年了。

  外圍實用函數的思考:基本上都針對SQL的產生,或資料庫函數的替換

  public String generateInsertSQL(DBType type,Object obj);//產生insert語句

  public String generateUpdateSQL(DBType type,Object obj);//產生update語句

  public String generateSelectSQL(DBType type,Object obj);//產生select語句

  總之這個函數工具箱的思路有這幾條:

  1.使用函數,而不是使用環境來代替JDBC或應用伺服器。

  2.使用成熟的SQL,而不是自創語言,最多增加SQL前置處理器,將一些函數轉成資料庫相關,簡單的文本功能。

  3.保持對各種環境的相容性。對象是乾淨的,當然如果用AOP就很難說對象幹不乾淨了,不過基本上應該適用於所有的環境中。

  缺點:由於沒有了環境,儲存對象有點麻煩,用SQL來解決批次更新和刪除,必要時增加幾個SQL語句產生器即可。儲存對象樹是一個大缺點,沒有非常好的辦法能夠將對象樹整個儲存下來而且效率非常高,只有上面提到的兩種不太完美的辦法,這都是因為JVM沒有提供對象狀態的原因。

  不過這樣用函數的方法來解決多繼承的問題還是比較乾淨舒服的,既可以動態,又可以靜態,隨心所欲,靈活性、效率和相容性兼得。



相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。