Hibernate的Fetch

越来越发现其实掌握 hibernate并不容易,Spring用起来其实简单多了,但是在用hibernate的时候真的是需要一定的时间积累,对一个项目组来说如果采用hibernate最好有一个对hibernate比较清楚的人否则碰到问题就会成为项目的风险。
我想告诉各位的是,掌握hibernate可能比你预期的难多了,当你轻松的告诉我,hibernate很简单的时候该是你自己多反省了. (只有一种情况例外,你是一个牛人)

好了,一个引子废话那么多,其实今天只是想先说一说hibernate里的Fetch的作用.

大家都知道,在hibernate里为了性能考虑,引进了lazy的概念,这里我们以Parent和Child为模型来说明,

public class Parent implements Serializable {

    /** identifier field */
    private Long id;

    /** persistent field */
    private List childs;

    //skip all getter/setter method

  
}  

public class Child implements Serializable {

    /** identifier field */
    private Long id;

    /** persistent field */
    private net.foxlog.model.Parent parent;

    //skip all getter/setter method

}
在我们查询Parent对象的时候,默认只有Parent的内容,并不包含childs的信息,如果在Parent.hbm.xml里设置lazy=”false”的话才同时取出关联的所有childs内容.

问题是我既想要hibernate默认的性能又想要临时的灵活性该怎么办?  这就是fetch的功能。我们可以把fetch与lazy=”true”的关系类比为事务当中的编程式事务与声明式事务,不太准确,但是大概是这个意思。

总值,fetch就是在代码这一层给你一个主动抓取得机会.

Parent parent = (Parent)hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session session) 
throws HibernateException, SQLException {
                Query q = session.createQuery(
                        ”from Parent as parent ”+
                                ” left outer join fetch parent.childs ” +
                                ” where parent.id = :id”
                );
                q.setParameter(”id”,new Long(15));
                return (Parent)q.uniqueResult();
            }

        });

        Assert.assertTrue(parent.getChilds().size() > 0);

你可以在lazy=”true”的情况下把fetch去掉,就会报异常. 当然,如果lazy=”false”就不需要fetch了

有一个问题,使用Fetch会有重复记录的现象发生,我们可以理解为Fetch实际上不是为Parent服务的,而是为
Child服务的.所以直接取Parent会有不匹配的问题.

============================================================

update:以上有些结论错误,实际上在hibernate3.2.1版本下测试,可以不出现重复记录,

public void testNPlusOne() throws Exception{
        List list = (List)hibernateTemplate.execute(new HibernateCallback() {
            public Object doInHibernate(Session session)
 throws HibernateException, SQLException {
                Query q = session.createQuery(
                        ”select distinct p from net.foxlog.model.Parent
                           p inner join fetch p.childs”
                );
                return q.list();
            }

        });

        //((Parent)(list.get(0))).getChilds();
        System.out.println(”list size = ” + list.size());
        for(int i=0;i<list.size();i++){
            Parent p = (Parent)list.get(i);
            System.out.println(”===parent = ” + p);
            System.out.println(”===parent’s child’s length = ” + p.getChilds().size());
        }

    }

打印结果如下:
Hibernate: select distinct parent0_.id as id2_0_, childs1_.id as id0_1_, 
childs1_.parent_id as parent2_0_1_, childs1_.parent_id as parent2_0__, 
childs1_.id as id0__ from parent parent0_ inner join child childs1_ on
 parent0_.id=childs1_.parent_id
list size = 3
===parent = net.foxlog.model.Parent@1401d28[id=14]
===parent’s child’s length = 1
===parent = net.foxlog.model.Parent@14e0e90[id=15]
===parent’s child’s length = 2
===parent = net.foxlog.model.Parent@62610b[id=17]
===parent’s child’s length = 3

另外,如果用open session in view模式的话一般不用fetch,但首先推荐fetch,如果非用的话因为有N
+1的现象,所以可以结合batch模式来改善下性能.

欢迎光临本站!请 订阅本站Feed 获得最新信息
转载请注明文章转载自:钱本草 [http://www.qbencao.com]
本文链接地址:Hibernate的Fetch

Tags: ,  | 日期:  2008-08-26|  分类:  Java, 编程开发| 阅读次数: 30 
上一篇文章:   Tapestry学习笔记

“Hibernate的Fetch”已经有3 个评论

  1.  

    孙兄 问下哦, 为什么yahoo统计的js 加载这么慢 能缓存到本地么?
    这个问题很白痴 但我真的为它所累…

    似乎google分析的js代码更慢.

  2.  

    是啊 这两个统计代码超级慢
    我原来用google的 后来就不用了 太慢了
    缓存本地似乎不大可能吧

  3.  

    那就算了…唉…

我来说两句

Powered by WordPress | Blue Weed by Blog Oh! Blog | Entries (RSS) and Comments (RSS)