2.事務(wù)處理。這點(diǎn)上更容易出問(wèn)題,相對(duì)于各種各樣的事務(wù)管理器,要兼容是一個(gè)大問(wèn)題,總歸在各種應(yīng)用服務(wù)器上有很多問(wèn)題。其本質(zhì)在于創(chuàng)建了一個(gè)自我數(shù)據(jù)存取小環(huán)境,必然面臨各種兼容問(wèn)題。
3.hql語(yǔ)言。建立對(duì)象查詢語(yǔ)言,類(lèi)sql,但是不同于任何一種sql,調(diào)試環(huán)境復(fù)雜。本質(zhì)在于創(chuàng)建了一種語(yǔ)言,增加學(xué)習(xí)成本。
減化hibernate,將其退化成一個(gè)sql生成器,既可以保留原有的主要功能,又可以兼容各種應(yīng)用服務(wù)器和數(shù)據(jù)庫(kù)服務(wù)器,另外還不需要學(xué)習(xí)hql語(yǔ)言。
只需要一系列的功能函數(shù),作一下包裝,再根據(jù)不同數(shù)據(jù)庫(kù)生成不同的sql即可,連數(shù)據(jù)庫(kù)類(lèi)型都不用指定,因?yàn)閺腸onnection中可以獲得數(shù)據(jù)庫(kù)類(lèi)型屬性。
假想中的api:
public object resultmapobject(resultset rs,string xml) //一行映射單個(gè)對(duì)象,可以用xml綁定,也可以不用。
public list sqlmapobjects(connection conn,string []sqls,string xml) //將一堆sql映射成一個(gè)對(duì)象樹(shù),可以用xml來(lái)描述綁定,也可以不用,僅使用ror方式的約定。
借助jdbc和sql可以構(gòu)建整個(gè)數(shù)據(jù)存取層。
映射單個(gè)對(duì)象的代碼,將一行記錄映射成單個(gè)對(duì)象。sql可以是任意的。
    connection conn=drivermanager.getconnection(url);
    preparedstatement ps = conn.preparestatement(sql);
    resultset rs = ps.executequery();
    while(rs.next())
    {
      user=(users)resultmapobject(rs);
      //todo 可以使用user
    }
映射對(duì)象樹(shù)。
    /*
    sale_orders銷(xiāo)售訂單表
    sale_order_details銷(xiāo)售訂單細(xì)表
    products商品表
    product_catalogs商品類(lèi)別表
    從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映射的,但是無(wú)法得知一對(duì)一還是一對(duì)多還是多對(duì)多的關(guān)系,所以一律建成多對(duì)多關(guān)系。
    list l=sqlmapobjects(conn,sqls);
    /*
    l的結(jié)構(gòu):
    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銷(xiāo)售訂單表
    sale_order_details銷(xiāo)售訂單細(xì)表
    products商品表
    product_catalogs商品類(lèi)別表
    從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 version="1.0"?>
<mapobject>
<!--類(lèi)似hibernate的映射,但是更容易理解,而且可以省略字段映射-->
    <object tablename="sale_orders" class="org.test.pojo.saleorder">
        <onetomany tablename="sale_order_details" class="org.test.pojo.saleorderdetail">
        <!--主細(xì)表映射-->
            <parentkey>id</parentkey>
            <childkey>id</childkey>
        </onetomany>
        <!--字段映射可選,一般是相同或根據(jù)ror規(guī)則-->
        <fieldmap>可選...</fieldmap>
    </object>
    <object tablename="sale_order_details" class="org.test.pojo.saleorderdetail">
        <!-- 附加代碼表映射1對(duì)1關(guān)系 -->
        <onetoone tablename="products" class="org.test.pojo.product">
            <parentkey tablename="sale_order_details">product_id</parentkey>
            <childkey tablename="products">id</childkey>
        </onetomany>
        <fieldmap>可選...</fieldmap>
    </object>
    <object tablename="sale_order_details" class="org.test.pojo.saleorderdetail">
        <onetoone tablename="product_catalogs" class="org.test.pojo.productcatalog">
            <parentkey tablename="sale_order_details">product_catalog_id</parentkey>
            <childkey tablename="product_catalogs">id</childkey>
        </onetomany>
        <fieldmap>可選...</fieldmap>
    </object>
    <object tablename="product_catalogs" class="org.test.pojo.productcatalog">
        <fieldmap>可選...</fieldmap>
    </object>
</mapobject>
     */
    string xml="...";
    //帶xml映射
    list l=sqlmapobjects(conn,sqls,xml);
    /*
    l的結(jié)構(gòu):
    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)
     */
    當(dāng)然類(lèi)要事先寫(xiě)好,這里就不詳細(xì)寫(xiě)了。
保存問(wèn)題更嚴(yán)重,取出來(lái)用sql映射已經(jīng)可以很好地解決了,基本上一個(gè)函數(shù)、一群sql,加上少少的xml就可以表達(dá)清楚了,但是這不能解決保存對(duì)象的問(wèn)題。
假想中的保存api。
public void saveobject(connection conn, object obj,string xml); //保存單個(gè)對(duì)象,簡(jiǎn)單地將對(duì)象擴(kuò)展成sql,允許xml映射,也可以不映射
public void saveobjects(connection conn, list objs, string xml); //將對(duì)象樹(shù)保存到數(shù)據(jù)庫(kù)
上一篇取出的list或人工組合的list可以用saveobjects來(lái)保存,這個(gè)函數(shù)的任務(wù)就比較重了,因?yàn)闆](méi)有狀態(tài),所以要判斷修改過(guò)非常麻煩。
一種思路是在對(duì)象是增加屬性,然后由開(kāi)發(fā)者維護(hù),比如界面上是否修改很有可能是有狀態(tài)位的,這個(gè)狀態(tài)位就可以用起來(lái),然后函數(shù)根據(jù)這個(gè)狀態(tài)位來(lái)判斷是否去更新。
一種思路是從class本身中就得知對(duì)象是否被改過(guò),類(lèi)似aop,在修改的時(shí)候記錄一下,然后函數(shù)來(lái)判斷是否改過(guò),然后組成sql來(lái)更新。
至于批量修改是強(qiáng)項(xiàng),直接用sql即可,學(xué)習(xí)sql比hql的成本要低,畢竟這么多年了。
外圍實(shí)用函數(shù)的思考:基本上都針對(duì)sql的生成,或數(shù)據(jù)庫(kù)函數(shù)的替換
public string generateinsertsql(dbtype type,object obj);//生成insert語(yǔ)句
public string generateupdatesql(dbtype type,object obj);//生成update語(yǔ)句
public string generateselectsql(dbtype type,object obj);//生成select語(yǔ)句
總之這個(gè)函數(shù)工具箱的思路有這幾條:
1.使用函數(shù),而不是使用環(huán)境來(lái)代替jdbc或應(yīng)用服務(wù)器。
2.使用成熟的sql,而不是自創(chuàng)語(yǔ)言,最多增加sql預(yù)處理器,將一些函數(shù)轉(zhuǎn)成數(shù)據(jù)庫(kù)相關(guān),簡(jiǎn)單的文本功能。
3.保持對(duì)各種環(huán)境的兼容性。對(duì)象是干凈的,當(dāng)然如果用aop就很難說(shuō)對(duì)象干不干凈了,不過(guò)基本上應(yīng)該適用于所有的環(huán)境中。
缺點(diǎn):由于沒(méi)有了環(huán)境,保存對(duì)象有點(diǎn)麻煩,用sql來(lái)解決批量更新和刪除,必要時(shí)增加幾個(gè)sql語(yǔ)句生成器即可。保存對(duì)象樹(shù)是一個(gè)大缺點(diǎn),沒(méi)有非常好的辦法能夠?qū)?duì)象樹(shù)整個(gè)保存下來(lái)而且效率非常高,只有上面提到的兩種不太完美的辦法,這都是因?yàn)閖vm沒(méi)有提供對(duì)象狀態(tài)的原因。
不過(guò)這樣用函數(shù)的方法來(lái)解決多繼承的問(wèn)題還是比較干凈舒服的,既可以動(dòng)態(tài),又可以靜態(tài),隨心所欲,靈活性、效率和兼容性兼得。
新聞熱點(diǎn)
疑難解答
圖片精選