Hibernate多表查询、查询优化策略(四)

多表HQL

private static void innerJoin(){
        //sql内连接  隐式内连接 select * from A,B where b.aid = a.id
        //          显示内连接 select * from A inner join B on b.aid = a.id
        //hql内连接 =>类似原生sql 返回合并的
        Query query = session.createQuery("from Category c inner join c.products");
        List<Object> objs = query.list();
        for(Object o : objs){
            System.out.println(o);
        }
    }
    private static void innerJoinfetch(){
        //迫切hql内连接 =>帮我进行封装
        Query query = session.createQuery("from Category c inner join fetch c.products");
        List<Category> categorys = query.list();
        for(Category o : categorys){
            System.out.println(o.getCname());
            for(Product p : o.getProducts()){
                System.out.println(p.getPname());
            }
        }
    }
    private static void leftJoin(){
        //外连接 左外连接 select * from A left [outer] join B on b.aid = a.id
        //hql 左连接
        Query query = session.createQuery("from Category c left join c.products");
        List<Object> objs = query.list();
        for(Object o : objs){
            System.out.println(o);
        }
    }

    private static void leftJoinfetch(){
        //hql 左连接 迫切
        Query query = session.createQuery("from Category c left join fetch c.products");
        List<Category> categorys = query.list();
        for(Category o : categorys){
            System.out.println(o.getCname());
            for(Product p : o.getProducts()){
                System.out.println(p.getPname());
            }
        }
    }
    private static void rightJoin(){
        //外连接 右外连接 select * from A right [outer] join B on b.aid = a.id
        //hql右连接
        Query query = session.createQuery("from Category c right join c.products");
        List<Object> objs = query.list();
        for(Object o : objs){
            System.out.println(o);
        }
    }

    private static void rightJoinfetch(){
        //外连接 右外连接 select * from A right [outer] join B on b.aid = a.id
        //hql右连接 迫切
        Query query = session.createQuery("from Category c right join fetch c.products");
        List<Category> categorys = query.list();
        for(Category o : categorys){
            System.out.println(o.getCname());
            for(Product p : o.getProducts()){
                System.out.println(p.getPname());
            }
        }
    }

Criteria(QBC)离线查询对象

        //传统criteria是依赖于session的
        Criteria criteria = session.createCriteria(Category.class);
        criteria.add(Restrictions.eq("cid",1));
        Category c = (Category) criteria.uniqueResult();
        System.out.println(c.getCname());

        //离线的criteria 凭空创建
        //service/web层
        DetachedCriteria dc = DetachedCriteria.forClass(Category.class);
        dc.add(Restrictions.gt("cid",0));
        //dao层
        Criteria criter = dc.getExecutableCriteria(session);
        List<Category> categories =  criteria.list();
        for(Category ca : categories){
            System.out.println(ca.getCname());
            for(Product p : ca.getProducts()){
                System.out.println(p.getPname());
            }
        }

查询优化策略

懒加载(延迟加载):使用hibernate查询一个对象的时候,查询其关联对象,应该如何查询。是hibernate的一种优化手段。

类级别查询

  session对象的load方法默认就是延迟加载, 可以在对象对应的配置文件中 class节点中配置lazy属性控制是否启用。如果false则会跟get没有任何区别。

    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        //get方法:立即加载,执行时立即发送sql语句
        Category c = session.get(Category.class,1);
        System.out.println(c);

        //延迟加载:仅仅获得没有使用,不会查询 返回代理对象
        Category c1 = session.load(Category.class,2);
        //在使用对象的属性时才会进行查询
        System.out.println(c1.getCname());
    }

关联级别查询

  集合关联级别

public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        //只返回Category表
        Category c = session.get(Category.class,1);
        System.out.println(c.getCname());
        //懒加载 与此Category表相关联的Product表 使用时 才去加载
        Set<Product> ps  = c.getProducts(); //集合关联级别
        for(Product p : ps){
            System.out.println(p.getPname());
        }

    }

附上配置文件Category.hbm.xml

<hibernate-mapping package="com.hibernate.domain">
    <class name="Category" table="Category" lazy="true">
        <id name="cid" column="cid">
            <generator class="native"/>
        </id>
        <property name="cname"/>
        <!--lazy:集合关联级别 是否懒加载 true(默认) false extra(极其懒惰-如果只获得集合的size,他会用count去查询)
            fetch(加载策略-使用什么类型的sql语句加载集合数据):
                select(默认):单表查询加载
                join:使用多表查询加载集合(无论是否启用懒加载,都一下多表查询回来)
                subselect:使用子查询加载集合(调用集合时,使用子查询语句)
            -->
        <set name="products" inverse="true" lazy="true" fetch="select">
            <key column="cpid"></key>
            <one-to-many class="Product"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

  关联属性级别

    public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Product p = session.get(Product.class,1);
        //根据产品去获得分类信息 执行如下时才会去数据库获取
        Category c = p.getCategory(); //属性关联级别
        System.out.println(c.getCname());
    }

  配置xml解析

<hibernate-mapping package="com.hibernate.domain">
    <class name="Product" table="Product">
        <id name="pid">
            <generator class="native"/>
        </id>
        <property name="pname"/>

        <!--fetch(加载的sql语句):
                select(默认):使用单表查询
                join:使用多表查询
            lazy(加载时机):
                proxy(默认):由Category的类级别加载策略(Category中 class元素中 lazy)决定
                false:立即加载
        -->
        <many-to-one name="category" class="Category" column="cpid" fetch="" lazy=""></many-to-one>
    </class>
</hibernate-mapping>

批量抓取

public static void main(String[] args) {
        Session session = HibernateUtils.openSession();
        Query query = session.createQuery("from Category");
        List<Category> categories = query.list();
        for(Category c : categories){
            for(Product p : c.getProducts()){ //categories数量为几 这里就要执行几次sql查询c.getProducts()
                System.out.println(p.getPname());
            }
        }
    }

category.hbm.xml

<hibernate-mapping package="com.hibernate.domain">
    <class name="Category" table="Category" lazy="true">
        <id name="cid" column="cid">
            <generator class="native"/>
        </id>
        <property name="cname"/>
        <!--batch-size:查询集合时一次查询多少个 默认1个 所以每次都会生成sql语句 -->
        <set name="products" inverse="true" lazy="true" fetch="select" batch-size="10">
            <key column="cpid"></key>
            <one-to-many class="Product"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

猜你喜欢

转载自www.cnblogs.com/baidawei/p/9064758.html