首 页 | 新 闻 | 技术中心 | 第二书店 | 《程序员》 | 《开发高手》 | 社 区 | 黄 页 | 人 才
移 动专 题SUNIBM微 软微 创精 华Donews人 邮
我的技术中心 
我的分类 我的文档
全部文章 发表文章
专栏管理 使用说明



 RSS 订阅 
最新文档列表
Windows/.NET
.NET  (rss)    
Visual C++  (rss)    
Delphi  (rss)    
Visual Basic  (rss)    
ASP  (rss)    
JavaScript  (rss)    
Java/Linux
Java  (rss)    
Perl  (rss)    
综合
其他开发语言  (rss)    
文件格式  (rss)    
企业开发
游戏开发  (rss)    
网站制作技术  (rss)    
数据库
数据库开发  (rss)    
软件工程
其他  (rss)    

积极原创作者 
nizhigang2000 (3)
hongbo781202 (81)
Kendiv (113)
TechnoFantasy (52)
feifei1018 (19)
coofucoo (108)
qingrun (67)
btbtd (83)
longrujun (64)
cyz1980 (101)
CSDN - 文档中心 - Java 阅读:615   评论: 0    参与评论
标题   Hibernate特点与思考     选择自 baggio785 的 Blog
关键字   Hibernate特点与思考
出处  

转载:转载请保留本信息,本文来自http://www.matrix.org.cn/resource/news/381_Hibernate.html

magicgod 昨天在他的blog上发布了一篇关于Hibernate的特点思考的文章。

原文:

想了很长时间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"
    };

    /*
<?xml version="1.0"?>
<MapObject>
<!--类似hibernate的映射,但是更容易理解,而且可以省略字段映射-->
    <Object tablename="sale_orders" class="org.test.pojo.SaleOrder">
        <OneToMany tablename="sale_order_details" class="org.test.pojo.SaleOrderDetail">
        <!--主细表映射-->
            <ParentKey>id</ParentKey>
            <ChildKey>id</ChildKey>
        </OneToMany>
        <!--字段映射可选,一般是相同或根据ROR规则-->
        <FieldMap>可选...</FieldMap>
    </Object>
    <Object tablename="sale_order_details" class="org.test.pojo.SaleOrderDetail">
        <!-- 附加代码表映射1对1关系 -->
        <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的结构:
    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没有提供对象状态的原因。

不过这样用函数的方法来解决多继承的问题还是比较干净舒服的,既可以动态,又可以静态,随心所欲,灵活性、效率和兼容性兼得。

关注:
magicgod的Blog
Hibernate论坛

对此,你有何看法?


相关文章
对该文的评论