Hibernate学习笔记(3)

1.Hibernate的检索方式

1.1通过对象导航

根据已经加载的对象导航到其他对象。

Customer c1 = new Customer("张三");

           Ordero1 = new Order("N001");

           Ordero2 = new Order("N002");

           Ordero3 = new Order("N003");

           /*

            * o1关联c1,而c1没有关联o1

            * c1关联o2,o3,而o2,o3没有管关联c1

            * 两个域对象的映射文件都有cascade="save-update"属性

            * session.save(c1) 插入几条记录?  3

            * session.save(o1) 插入几条记录?  4

            * session.save(o2) 插入几条记录?  1

            */

           //o1单向关联c1

           o1.setCustomer(c1);

           //c1单向关联o2和o3

           c1.getOrders().add(o2);

           c1.getOrders().add(o3);

//        session.save(c1);//3条,c1,o2,o3被保存了

//        session.save(o1);//4条,o1,c1,o2,o3都被保存了

           session.save(o2);//1条,o2被保存了

1.2通过session.get(Xxx.class, id)方法和session.load(Xxx.class, id)方法

按照对象的 OID 来检索对象。

eg:

Order order =(Order)session.get(Order.class, 1);

Order order = (Order)session.load(Order.class,1);

1.3使用面向对象的 HQL 查询语言

HQL(HibernateQuery Language) 面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能:

A在查询语句中设定各种查询条件

B支持投影查询, 即仅检索出对象的部分属性

C支持分页查询

D支持连接查询

E支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字

F提供内置聚集函数, 如 sum(), min()和 max()

G支持动态绑定参数

 

HQL和SQL的关系:

1.HQL 查询语句是面向对象的, Hibernate 负责解析 HQL 查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句. HQL 查询语句中的主体是域模型中的类及类的属性。

2.SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段.。

 

注意:使用HQL语言查询数据库时,是不会出现表中的字段和表名的,只有类名和类的属性出现,sql的关键字是可以出现的。

 

常用HQL语句:

FROMCustomer 简单查询

           /*//简单查询,查询所有客户

           Stringhql = "FROM Customer"; //关键字from+类名

           Queryquery = session.createQuery(hql);

           List<Customer>customers = query.list();

           for(Customer c : customers) {

                 System.out.println(c.getName());

           }

FROMCustomer AS c WHERE c.name = ?            query.setString(0,"张三") 根据名字查询

FROMCustomer AS c WHERE c.name = :name           query.setString("name","张三")

 

/*

            * 根据名字查询客户

            * from + 类名 [as] 别名 where 别名.属性名= ?/:xx

            * 如果要根据id查询客户可以直接使用session.get(Customers.class, 1)

            */

/*//           Stringhql = "FROM Customer AS c WHERE c.name = ?";

           Stringhql = "FROM Customer AS c WHERE c.name = :name"; //as可省略

           Queryquery = session.createQuery(hql);

//        query.setString(0,"张三");//为占位符?赋值,索引从0开始,jdbc的从1开始

           query.setString("name","张三");//冒号:后面的名字任何,可以为:xx,:yy等等,赋值时只要写名字就可以了,冒号不必写

           Customerc = (Customer) query.uniqueResult();//因为根据名字查询的结果只用一条,无需用集合接收

           System.out.println(c.getName());*/

FROMjava.lang.Object 多态查询

      /*

            * 多态查询(是指查询出当前类及所有子类的实例)

            */

/*        Stringhql = "FROM java.lang.Object"; //这里要写全类名,否则在当前映射文件指定的包下找不到Object类会出错。

           Queryquery = session.createQuery(hql);

            List<Object[]> objects = query.list();//返回List集合,里面装了Object数组,数组的元素为客户和订单

            for (Object o : objects) {

                 if(oinstanceof Customer) {

                      Customerc = (Customer) o;

                      System.out.println(c.getName());

                 }else if(o instanceof Order) {

                      Orderorder = (Order) o;

                      System.out.println(order.getOrderNum());

                 }

           }*/

FROMOrder o ORDER BY o.id DESC 排序

           //对查询结果进行排序

/*        Stringhql = "FROM Order o ORDER BY o.id ASC";

           Queryquery = session.createQuery(hql);

           List<Order>orders = query.list();

           for(Order o : orders) {

                 System.out.println(o.getOrderNum());

           }*/

分页查询:

query.setFirstResult(int firstResult): 设定从哪一个对象开始检索, 参数 firstResult 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 默认情况下, Query 从查询结果中的第一个对象开始检索。

query.setMaxResult(int maxResults): 设定一次最多检索出的对象的数目.

           //分页查询

           Stringhql = "FROM Order o ORDER BY o.id ASC";

           Queryquery = session.createQuery(hql);

           //设置从第几条开始查询,索引从0开始

           query.setFirstResult(2);

           //设置每次查询几条数据

            query.setMaxResults(2);

           List<Order>orders = query.list();

           for(Order o : orders) {

                 System.out.println(o.getOrderNum());

           }

 

在映射文件中配置HQL语句:

           <!-- name:hql语句的名字,在java代码中要使用 -->

           <query name="findCustomerByName">

                 <![CDATA[FROM Customer cWHERE c.name = ?]]>

           </query>

--------------------------

           //通过*.hbm.xml配置hql语句,<query>要放在<class>外

           Queryquery = session.getNamedQuery("findCustomerByName");

           //为占位符?赋值

           query.setString(0,"张三");

           List<Customer>customers = query.list();

           for (Customer c :customers) {

                 System.out.println(c.getName());

           }

模糊查询 like  %xx%:

//模糊查询

           Stringhql = "FROM Customer c where c.name like ?"; //占位符中不用写通配符

           Queryquery = session.createQuery(hql);

           query.setString(0,"%张%"); //给占位符设置值时要写通配符

           List<Customer>customers = query.list();

           for (Customer c :customers) {

                 System.out.println(c.getName());

           }

连接查询:

      //连接查询

           Stringhql = "FROM Customer c LEFT OUTER JOIN c.orderSet o WHEREc.name = ?";

           Queryquery = session.createQuery(hql);

           query.setString(0,"张三");

           /*

            * List的元素为Object数组objects

            * objects的元素为Object数组os

            * os的元素为客户或订单

            */

            List<Object[]> objects = query.list();

            for (Object[] os :objects) {

                  for (Object  o : os) {

                            if(o instanceof Customer) {

                                  Customerc = (Customer) o;

                                  System.out.println(c.getName());

                            }elseif(o instanceof Order) {

                                  Orderorder = (Order) o;

                                  System.out.println(order.getOrderNum());

                            }

                  }

           }

投影查询:

查询结果仅包含实体的部分属性.通过 SELECT 关键字实现

           //投影查询

           Stringhql = "SELECT c.name FROM Customer c"; //只查询名字

           Queryquery = session.createQuery(hql);

           List<Object>objects = query.list();

           for (Object os :objects) {

                 System.out.println(os);

           }

报表查询:

报表查询用于对数据分组和统计,与 SQL 一样, HQL 利用 GROUP BY 关键字对数据分组, 用 HAVING 关键字对分组数据设定约束条件.

在 HQL 查询语句中可以调用以下聚集函数:

count()

min()

max()

sum()

avg()

SELECT count(c) FROM Customer c

SELECT sum(c.id),avg(c.id) FROM Customer c

SELECT min(c.id),max(c.id) FROM Customer c

FROM Order o GROUP BY o.customer

子查询:

select o.orderNum from Order o whereo.customer.id = (select c.id from Customer c where c.name=?)

2.Hibernate的检索策略

立即检索: 立即加载检索方法指定的对象

延迟检索: 延迟加载检索方法指定的对象

2.1类级别:(建议lazy=false,即立即检索)

session.get(xx,xx)方法:返回真实对象或null

1.无论*.hbm.xml中<class>的属性lazy=”true”(默认值)还是lazy=”false”,都是立即检索,即当get方法一执行完就查询数据库。

session.load(xx,xx)方法:返回的对象一定是非空的(代理对象或真实对象)

1.当*.hbm.xml中<class>的属性lazy=”true” (默认值)时,延迟检索,返回的是代理对象,对象是要真正返回对象的子类。获取id属性值时是不会产生sql的(即不会查询数据库)。执行commit方法提交时也不会。获取非id属性值时才会产生sql,即查询数据库(如果数据库没有对应的记录会发生对象找不到异常)。

2.当*.hbm.xml中<class>的属性lazy=”false” (默认值)时,立即检索, 执行玩load方法就查询数据库了,返回真正的对象,而不是代理对象。

2.2关联级别(有集合存在): (建议lazy=true,即延迟检索)

session.get(xx,xx)方法:只要set的lazy属性为false就立即检索

<class lazy="true"/> +<set lazy="true"/>

<class lazy="false"/> +<set lazy="true"/>

在需要取得所有订单时,才临时查询所有订单。

 

<class lazy="true"/> +<set lazy="false"/>

<class lazy="false"/> +<set lazy="false"/>

在查询客户时,将客户关联的所有订单都查询出来。

 

session.load(xx,xx)方法:只有class和set的lazy属性同时为false才立即检索

<class lazy="true"/> +<set lazy="true"/>

<class lazy="true"/> +<set lazy="false"/>

<class lazy="false"/> +<set lazy="true"/>

在需要取得所有订单时,才临时查询所有订单。 

 

<class lazy="false"/> +<set lazy="false"/>

在查询客户时,将客户关联的所有订单都查询出来。

get方法和load方法两次加载相同的对象:立即和延迟都是第一次查询,第二次不查询。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值