Hibernate查询方式

来源:互联网 发布:照片制作软件 编辑:程序博客网 时间:2024/05/21 10:46
Hibernate查询方式

OID查询
     它就是根据id查询一个实体
     涉及的方法:
          get(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。
          load(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。
Hibernate的检索策略
     类级别检索策略:
          get方法:
               它永远都是立即加载。返回的对象是实体类类型。
               立即加载的含义:不管用不用,都马上发起查询。
          load方法:
               它默认是延迟加载。返回的是实体类对象的代理对象。
               它可以通过配置的方式改为立即加载。配置的位置是映射文件的class标签。
               涉及的属性是:lazy。含义就是是否延迟加载。 取值true延迟加载(默认值) false不是延迟加载
               延迟加载的含义:什么时候用,什么时候真正发起查询。

测试OID检索方式

[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3. import org.hibernate.Session;  
  4. import org.hibernate.Transaction;  
  5. import org.junit.Test;  
  6.   
  7. import com.pc.hibernate.domain.Customer;  
  8. import com.pc.hibernate.utils.HibernateUtils;  
  9.   
  10. /** 
  11.  * Hibernate中的查询方式: 
  12.  *         OID查询: 
  13.  *             它就是根据id查询一个实体 
  14.  *         涉及的方法: 
  15.  *             get(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。 
  16.  *            load(Class clazz,Serializable id):参数1是要查询的实体字节码,参数2:是要查询的id。 
  17.  * 
  18.  * Hibernate的检索策略 
  19.  *       类级别检索策略: 
  20.  *          get方法: 
  21.  *             它永远都是立即加载。返回的对象是实体类类型。 
  22.  *             立即加载的含义:不管用不用,都马上发起查询。 
  23.  *         load方法: 
  24.  *             它默认是延迟加载。返回的是实体类对象的代理对象。 
  25.  *             它可以通过配置的方式改为立即加载。配置的位置是映射文件的class标签。 
  26.  *             涉及的属性是:lazy。含义就是是否延迟加载。 取值true延迟加载(默认值) false不是延迟加载 
  27.  *             延迟加载的含义:什么时候用,什么时候真正发起查询。 
  28.  * @author Switch 
  29.  * 
  30.  */  
  31. public class TestOIDQuery {  
  32.     /** 
  33.      * 需求: 
  34.      *     查询id为1的客户 
  35.      */  
  36.     @Test  
  37.     public void test1() {  
  38.         Session session = HibernateUtils.getCurrentSession();  
  39.         Transaction transaction = session.beginTransaction();  
  40.         Customer customer = session.get(Customer.class, 1L);  
  41.         transaction.commit();  
  42.         // 输出1和客户信息  
  43.         System.out.println(customer.getCustId());  
  44.         System.out.println(customer);  
  45.     }  
  46.   
  47.     /** 
  48.      * 需求: 
  49.      *     查询id为1的客户 
  50.      */  
  51.     @Test  
  52.     public void test2() {  
  53.         Session session = HibernateUtils.getCurrentSession();  
  54.         Transaction transaction = session.beginTransaction();  
  55.         Customer customer = session.load(Customer.class, 1L);  
  56.         transaction.commit();  
  57.         // 输出1和报错could not initialize proxy - no Session  
  58.         // 当<class name="Customer" table="cst_customer" lazy="false">时  
  59.         // 该方法正确,因为这时候已经不延迟加载了  
  60.         System.out.println(customer.getCustId());  
  61.         System.out.println(customer);  
  62.     }  
  63. }  


对象导航查询
     对象图导航检索方式是根据己经加载的对象,导航到他的关联对象 。它利用类与类之间的关系来检索对象 。譬如要查找一个联系人对应的客户,就可以由联系人对象自动导航找到联系人所属的客户对象。当然,前提是必须在对象关系映射文件上配置了多对一的关系。

     当我们两个实体类有关联关系时(一对多,多对一等等),在获取一个实体时,可以根据对象的方法,获取该实体关联对象的数据。
     customer.getLinkMans();获取当前客户下的所有联系人
     linkman.getCustomer();获取当前联系人所属客户。

[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3. import java.util.List;  
  4. import java.util.Set;  
  5.   
  6. import org.hibernate.SQLQuery;  
  7. import org.hibernate.Session;  
  8. import org.hibernate.Transaction;  
  9. import org.junit.Test;  
  10.   
  11. import com.pc.hibernate.domain.Customer;  
  12. import com.pc.hibernate.domain.LinkMan;  
  13. import com.pc.hibernate.utils.HibernateUtils;  
  14.   
  15. /** 
  16.  * 
  17.  * Hibernate中的查询方式: 
  18.  *         对象导航查询 
  19.  *             当我们两个实体类有关联关系时(一对多,多对一等等),在获取一个实体时,可以根据对象的方法,获取该实体关联对象的数据。 
  20.  *             customer.getLinkMans();获取当前客户下的所有联系人 
  21.  *             linkman.getCustomer();获取当前联系人所属客户。 
  22.  * 
  23.  * @author Switch 
  24.  */  
  25. public class TestObjectNavigationQuery {  
  26.     /** 
  27.      * 一般情况下我们都会有一个这样的方法:根据id查询一个实体。 
  28.      * 任何实体都应该有这么个方法 
  29.      */  
  30.     public Customer findById(Long custId){  
  31.         Session s = HibernateUtils.getCurrentSession();  
  32.         Transaction tx = s.beginTransaction();  
  33.         Customer c1 = s.get(Customer.class, custId);  
  34.         tx.commit();  
  35.         return c1;  
  36.     }  
  37.   
  38.     /** 
  39.      * 根据客户id查询联系人信息 
  40.      * @param custId 
  41.      * @return 
  42.      */  
  43.     public List<LinkMan> findLinkManByCid(Long custId){  
  44.         Session s = HibernateUtils.getCurrentSession();  
  45.         Transaction tx = s.beginTransaction();  
  46.         SQLQuery query = s.createSQLQuery("select * from cst_linkman where lkm_cust_id = ? ");  
  47.         query.setLong(0, custId);  
  48.         query.addEntity(LinkMan.class);  
  49.         @SuppressWarnings("unchecked")  
  50.         List<LinkMan> mans = query.list();  
  51.         tx.commit();  
  52.         return mans;  
  53.     }  
  54.   
  55.     /** 
  56.      * 需求: 
  57.      *     查询id为1的客户下的所有联系人 
  58.      */  
  59.     @Test  
  60.     public void test1(){  
  61.         // 传统的使用方式  
  62.         List<LinkMan> list = findLinkManByCid(1L);  
  63.         System.out.println(list);  
  64.   
  65.         Customer c = findById(1L);  
  66.         //对象导航查询  
  67.         // 需要将Customer上对应于LinkMan的关系检索策略的懒加载关闭  
  68.         Set<LinkMan> linkmans = c.getLinkMans();  
  69.         for(LinkMan linkMan : linkmans){  
  70.             System.out.println(linkMan);  
  71.         }  
  72.     }  
  73.   
  74.   
  75.     /** 
  76.      * 需求: 
  77.      *     查询id为5的联系人所属客户 
  78.      */  
  79.     @Test  
  80.     public void test2() {  
  81.         Session session = HibernateUtils.openSession();  
  82.         Transaction transaction = session.beginTransaction();  
  83.         LinkMan linkMan = session.get(LinkMan.class, 5L);  
  84.         // 对象导航查询  
  85.         System.out.println(linkMan.getCustomer());  
  86.         transaction.commit();  
  87.   
  88.     }  
  89.   
  90. }  


HQL查询
     HQL (Hibernate Query Language ) 是面向对象的查询语言,它和 SQL 查询语言有些相似 ,但它使用的是类、对象和属性的概念 ,而没有表和字段的概念 。在Hibernate提供的各种检索方式中 ,HQL是官方推荐的查询语言,也是使用最广泛的一种检索 方式。
     涉及的对象:
          Query
     如何获取Query:
          session.createQuery(String hql);
     HQL语句写法:
          表名用实体类名称替代
          字段名用实体类属性名称(get/set方法后面的部分,并且把首字母转小写)

     Hibernate 进行 多表查询与 SQL 其实是很相似的 ,但是 HQL 会在原来 SQL 分类的基础上又多出来一些操作 。

HQL  的多表连接查询的分类如下 :
  • 交叉连接
  • 内连接
    • 显式内连接
    • 隐式内连接
    • 迫切内连接
  • 外连接
    • 左外连接
    • 迫切左外连接

     其实这些连接查询语法大致都是一致的,就是HQL查询的是对象而SQL查询的是表。那么我们来比较一下SQL和HQL的连接查询。

SQL  连接查询
[sql] view plain copy
  1. SELECT  * FROM  cst_customer c INNER JOIN cst_linkman 1 ON c.cust_id = l.lkm_cust_id;  

HQL 连接的查询


[sql] view plain copy
  1. from Customer c inner join c.linkMans  

     在HQL中,我们不用写关联宇段了,因为客户中的联系人的集合其实对应的就是外键,所以我们在inner join的后面直接可以写 c.linkMans。
     迫切内连接其实就是在内连接的inner join后添加一个fetch关键字。

[sql] view plain copy
  1. from Customer c inner join fetch c.linkMans  

     内连接或是迫切内连接发送的底层SQL都是一样的,而且在生成的SQL语句中也没有fetch关键字,当然fetch本身就不是SQL语句的关键字。所以一定要注意,fetch只能在HQL中使用的,生成了SQL语句以后,fetch就消失了 。
     其实HQL内连接查询的和SQL的内连接查询到的结果集是一样的 ,都是两个表的交集部分的数据。
     然后在封装数据的时候,普通内连接会将属于客户的数据封装到Customer对象中,会将属于联系人的数据封装到LinkMan对象中,所以每条记录都会是装有两个对象的集合,所以封装以后的数据是 List<Object[ ]>,在Object[ ]中有两个对象一个是 Customer另一个是 LinkMan 。
     那么加了fetch以后,虽然查询到的数据是一样的,但是Hibernate发现HQL中有fetch就会将数据封装到一个对象中,把属于客户的数据封装到Customer对象中,将属于联系人的部分封装到Customer中的联系人的集合中,这样最后封装完成以后是一个 List<Customer> 中。

测试HQL方式
[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3. import java.util.List;  
  4.   
  5. import org.hibernate.Query;  
  6. import org.hibernate.Session;  
  7. import org.hibernate.Transaction;  
  8. import org.junit.Test;  
  9.   
  10. import com.pc.hibernate.domain.Customer;  
  11. import com.pc.hibernate.domain.LinkMan;  
  12. import com.pc.hibernate.utils.HibernateUtils;  
  13.   
  14. /** 
  15.  * Hibernate中的查询方式: 
  16.  *         HQL查询: 
  17.  *             它是使用HQL语句进行查询的。 HQL:Hiberante Query Language 
  18.  *         涉及的对象: 
  19.  *             Query 
  20.  *         如何获取Query: 
  21.  *             session.createQuery(String hql); 
  22.  *         HQL语句写法: 
  23.  *             表名用实体类名称替代 
  24.  *             字段名用实体类属性名称(get/set方法后面的部分,并且把首字母转小写) 
  25.  * 
  26.  * @author Switch 
  27.  */  
  28. public class TestHQLQuery {  
  29.     /** 
  30.      * 查询所有 
  31.      * 需求:查询所有客户 
  32.      */  
  33.     @Test  
  34.     public void test1() {  
  35.         Session session = HibernateUtils.openSession();  
  36.         Transaction transaction = session.beginTransaction();  
  37.         // 查询所有客户  
  38.         Query query = session.createQuery("from Customer");  
  39.         @SuppressWarnings("unchecked")  
  40.         List<Customer> customers = query.list();  
  41.         transaction.commit();  
  42.         for (Customer customer : customers) {  
  43.             System.out.println(customer);  
  44.         }  
  45.     }  
  46.   
  47.     /** 
  48.      * 条件查询: 
  49.      *     需求: 
  50.      *         查询客户级别是23的,客户名称带有 集 字的 
  51.      *  给HQL语句加条件用where 
  52.      *  HQL语句的参数占位符也可以使用? 
  53.      *  hibernate中,参数占位符是从0开始的。 
  54.      */  
  55.     @Test  
  56.     public void test2(){  
  57.         Session session = HibernateUtils.openSession();  
  58.         Transaction transaction = session.beginTransaction();  
  59.         // 查询客户级别是23的,客户名称带有 集 字的  
  60.         Query query = session.createQuery("from Customer where custLevel = ? and custName like ?");  
  61.         query.setString(0"23");  
  62.         query.setString(1"%集%");  
  63.         @SuppressWarnings("unchecked")  
  64.         List<Customer> customers = query.list();  
  65.         transaction.commit();  
  66.         for (Customer customer : customers) {  
  67.             System.out.println(customer);  
  68.         }  
  69.     }  
  70.   
  71.     /** 
  72.      * 具名查询: 
  73.      *     给参数占位符提供一个具体的名称 
  74.      * HQL语句中的写法: 
  75.      *         需要使用    :参数名称 
  76.      *         例如:        :custLevel    :custName 
  77.      * 参数站位符赋值的写法: 
  78.      *         需要注意:此处不能写冒号,直接写冒号后面的部分 
  79.      */  
  80.     @Test  
  81.     public void test3(){  
  82.         Session session = HibernateUtils.openSession();  
  83.         Transaction transaction = session.beginTransaction();  
  84.         // 查询客户级别是23的,客户名称带有 集 字的  
  85.         // 给参数占位符提供一个具体的名称  
  86.         Query query = session.createQuery("from Customer where custLevel = :custLevel and custName like :custName");  
  87.         query.setString("custLevel""23");  
  88.         query.setString("custName""%集%");  
  89.         @SuppressWarnings("unchecked")  
  90.         List<Customer> customers = query.list();  
  91.         transaction.commit();  
  92.         for (Customer customer : customers) {  
  93.             System.out.println(customer);  
  94.         }  
  95.     }  
  96.   
  97.   
  98.     /** 
  99.      * 排序查询: 
  100.      *      使用HQL语句,给查询结果排序 
  101.      * 
  102.      * HQL语句中的排序: 
  103.      *         order by 
  104.      *         asc:升序(默认值) 
  105.      *         desc:降序 
  106.      */  
  107.     @Test  
  108.     public void test4(){  
  109.         Session session = HibernateUtils.openSession();  
  110.         Transaction transaction = session.beginTransaction();  
  111.         // 按联系人ID降序排序联系人  
  112.         Query query = session.createQuery("from LinkMan order by lkmId desc");  
  113.         @SuppressWarnings("unchecked")  
  114.         List<LinkMan> linkMans = query.list();  
  115.         transaction.commit();  
  116.         for (LinkMan linkMan : linkMans) {  
  117.             System.out.println(linkMan);  
  118.         }  
  119.     }  
  120.   
  121.     /** 
  122.      * 分页查询 
  123.      * MySQL中分页关键字: 
  124.      *         Limit 
  125.      * limit的两个参数: 第一个参数:查询的开始记录索引。(它是从0开始的) 
  126.      *                    第二个参数:每次查询多少条记录。(它是固定的) 
  127.      * Hibernate中涉及的方法 
  128.      *         setFirstResult(int firstResult):查询的开始记录索引 
  129.      *         setMaxResults(int maxResults):每次查询多少条记录 
  130.      */  
  131.     @Test  
  132.     public void test5(){  
  133.         Session session = HibernateUtils.getCurrentSession();  
  134.         Transaction transaction = session.beginTransaction();  
  135.         //1.获取Query对象  
  136.         Query query = session.createQuery("from LinkMan");  
  137.         //2.使用Hibernate提供的方法来设置分页条件  
  138.         Integer firstResult = 0;  
  139.         Integer maxResults = 2;  
  140.         query.setFirstResult(firstResult);  
  141.         query.setMaxResults(maxResults);  
  142.         //3.执行query对象的方法  
  143.         @SuppressWarnings("unchecked")  
  144.         List<LinkMan> list = query.list();  
  145.         transaction.commit();  
  146.         for (LinkMan linkMan : list) {  
  147.             System.out.println(linkMan);  
  148.         }  
  149.     }  
  150.   
  151.     /** 
  152.      * 统计查询 
  153.      *       其实就是在HQL语句中使用聚合函数 
  154.      *         count() sum() avg() max() min() 
  155.      *      使用聚合函数查询时,如果没有group by,返回的结果集是一行一列的 
  156.      * 
  157.      *  聚合函数都不会计算为null的字段。 
  158.      *  
  159.      *  count(*)和count(主键)是一样的。 
  160.      */  
  161.     @Test  
  162.     public void test6(){  
  163.         Session session = HibernateUtils.getCurrentSession();  
  164.         Transaction transaction = session.beginTransaction();  
  165.         // 查询一共有多少个联系人  
  166.         Query query = session.createQuery("select count(lkmId) from LinkMan");  
  167.         Long count = (Long) query.uniqueResult();  
  168.         transaction.commit();  
  169.         System.out.println(count);  
  170.     }  
  171.   
  172.     /** 
  173.      * 投影查询: 
  174.      *      当我们查询实体对象时,并不需要所有字段信息,只查询部分,但是还想让他成为一个实体对象。其实就是用部分字段来投影出整个实体对象。 
  175.      * 使用要求: 
  176.      *     HQL语句: 
  177.      *         写法必须是  new 实体类名称(查询的字段) 
  178.      *         select new Customer(custId,custName) from Customer 
  179.      *         注意:如果你的实体类在工程中唯一,则可以直接写类名。如果实体类在工程中不唯一,需要写全限定类名。 
  180.      *  实体类要求: 
  181.      *      必须在实体类中提供一个相同参数列表的构造函数。 
  182.      *          
  183.      */  
  184.     @Test  
  185.     public void test71(){  
  186.         Session session = HibernateUtils.getCurrentSession();  
  187.         Transaction transaction = session.beginTransaction();  
  188.         // 只获取客户的ID和名字,并封装成客户对象  
  189.         Query query = session.createQuery("select new Customer(custId, custName) from Customer");  
  190.         @SuppressWarnings("unchecked")  
  191.         List<Customer> customers = query.list();  
  192.         transaction.commit();  
  193.         for (Customer customer : customers) {  
  194.             System.out.println(customer.getCustId() + " " + customer.getCustName());  
  195.         }  
  196.     }  
  197.   
  198.     @Test  
  199.     public void test72(){  
  200.         Session s = HibernateUtils.getCurrentSession();  
  201.         Transaction tx = s.beginTransaction();  
  202.         //1.获取Query对象  
  203.         Query query = s.createQuery("select custId,custName from Customer ");  
  204.         //2.执行query对象的方法  
  205.         @SuppressWarnings("unchecked")  
  206.         List<Object[]> list = query.list();  
  207.         tx.commit();  
  208.         for(Object[] os : list){  
  209.             System.out.println("----------每个数组中的内容------------");  
  210.             for(Object o : os){  
  211.                 System.out.println(o);  
  212.             }  
  213.         }  
  214.     }  
  215.   
  216.     /** 
  217.      * 左外连接查询和迫切左外连接查询的区别 
  218.      * 区别: 
  219.      *     返回的结果集不一样。在实际开发中用的不多,此处讲解就是为了说明他们之间的区别 
  220.      * 注意: 
  221.      *     Hibernate中没有右外连接 
  222.      * 
  223.      * Hibernate左外连接返回的数据:    
  224.      *         返回的是一个有Object数组组成的List集合,该数组中有两个对象。一个是主表实体,一个是从表实体。 
  225.      *         主表实体有可能重复 
  226.      */  
  227.     //左外连接查询  
  228.     @Test  
  229.     public void test81(){  
  230.         Session session = HibernateUtils.getCurrentSession();  
  231.         Transaction transaction = session.beginTransaction();  
  232.         //1.获取Query对象  
  233.         //sql语句的左外:select * from cst_customer c left outer join cst_linkman l on c.cust_id = l.lkm_cust_id;  
  234.         Query query = session.createQuery("from Customer c left join c.linkMans");  
  235.         //2.执行query对象的方法  
  236.         @SuppressWarnings("unchecked")  
  237.         List<Object[]> list = query.list();  
  238.         transaction.commit();  
  239.         for (Object[] objects : list) {  
  240.             System.out.println("------一组对象-------");  
  241.             for (Object object : objects) {  
  242.                 System.out.println(object);  
  243.             }  
  244.         }  
  245.     }  
  246.   
  247.     /** 
  248.      * 迫切左外连接查询: 
  249.      *         要想使用迫切,需要在查询HQL语句中加入一个关键字:fetch 
  250.      * Hibernate迫切左外连接返回的数据: 
  251.      *         返回的是左表实体对象的List集合,并且左表中对应右表的字段已经被填充 
  252.      */  
  253.     @Test  
  254.     public void test82(){  
  255.         Session session = HibernateUtils.getCurrentSession();  
  256.         Transaction transaction = session.beginTransaction();  
  257.         //1.获取Query对象  
  258.         Query query = session.createQuery("from Customer c left join fetch c.linkMans");  
  259.         //2.执行query对象的方法  
  260.         @SuppressWarnings("unchecked")  
  261.         List<Customer> customers = query.list();  
  262.         transaction.commit();  
  263.         for (Customer customer : customers) {  
  264.             System.out.println("------一组对象-------");  
  265.             System.out.println(customer);  
  266.             for (LinkMan linkMan : customer.getLinkMans()) {  
  267.                 System.out.println(linkMan);  
  268.             }  
  269.             System.out.println("");  
  270.         }  
  271.     }  
  272.   
  273.     /** 
  274.      * 使用HQL进行更新操作 
  275.      */  
  276.     @Test  
  277.     public void test9(){  
  278.         Session session = HibernateUtils.getCurrentSession();  
  279.         Transaction transaction = session.beginTransaction();  
  280.         //1.获取Query对象  
  281.         Query query = session.createQuery("update Customer set custName = ? where custId = ?");  
  282.         query.setString(0"XX公司");  
  283.         query.setString(1"1");  
  284.         //2.执行query对象的方法  
  285.         int result = query.executeUpdate();  
  286.         transaction.commit();  
  287.         System.out.println(result);  
  288.     }  
  289. }  


QBC查询
     QBC(Query By Criteria)是Hibernate提供的另一种检索对象的方式,它主要由Criteria 接口、Criterion接口和Expression类组成 。Criteria接口是Hibernate API中的一个查询接口,它需要由session进行创建。Criterion是Criteria的查询条件,在Criteria中提供了add(Criterion criterion)方法来添加查询条件。
     涉及的对象:
          Criteria
          DetachedCriteria
     获取的方式:
          session.createCriteria(Class clazz);参数指的是要查询的字节码
     添加条件的方法:
          Criteria的add方法
     添加条件涉及的对象:
          Restrictions

Restrictions类提供的方法
方法名
说明
Restrictions.eq
等于
Restrictions. allEq
使用 Map ,使用key/value进行多个等于的比较
Restrictions.gt
大于>
Restrictions.ge
大于等于>=
Restrictions.lt
小于
Restrictions.le
小于等于<=
Restrictions.between
对应 SQL 的 between 子句
Restrictions.like
对应 SQL 的 like 子句
Restrictions.in
对应 SQL 的 IN 子句
Restrictions.and
and 关系
Restrictions.or
or 关系
Restrictions.sqlRestriction
SQL 限定查询


离线条件检索
     DetachedCriteria 翻译为离线条件查询,因为它是可以脱离Session来使用的一种条件查询对象,我们都知道Criteria对象必须由Session对象来创建。那么也就是说必须先有Session才可以生成Criteria对象。而DetachedCriteria对象可以在其他层对条件进行封装。
     这个对象也是比较有用的,尤其在SSH整合以后这个对象经常会使用 。它的主要优点是做一些特别复杂的条件查询的时候,往往会在WEB层向业务层传递很多的参数,业务层又会将这些参数传递给DAO层。最后在DAO中拼接SQL完成查询。有了离线条件查询对象后,那么这些工作都可以不用关心了,我们可以在WEB层将数据封装好,传递到业务层,再由业务层传递给DAO完成查询。

测试QBC检索方式
[java] view plain copy
  1. package com.pc.hibernate.test.querymethod;  
  2.   
  3.   
  4. import java.util.List;  
  5.   
  6. import org.hibernate.Criteria;  
  7. import org.hibernate.Session;  
  8. import org.hibernate.Transaction;  
  9. import org.hibernate.criterion.DetachedCriteria;  
  10. import org.hibernate.criterion.Order;  
  11. import org.hibernate.criterion.Projections;  
  12. import org.hibernate.criterion.Restrictions;  
  13. import org.junit.Test;  
  14.   
  15. import com.pc.hibernate.domain.Customer;  
  16. import com.pc.hibernate.domain.LinkMan;  
  17. import com.pc.hibernate.utils.HibernateUtils;  
  18.   
  19. /** 
  20.  * Hibernate中的查询方式: 
  21.  *         QBC查询: 
  22.  *             Query By Criteria  它是一种更加面向对象的查询方式。 
  23.  *             它把查询条件都用方法封装了。里面的参数全都需要使用实体类的属性名称。 
  24.  *         涉及的对象: 
  25.  *             Criteria 
  26.  *             DetachedCriteria 
  27.  *         获取的方式: 
  28.  *             session.createCriteria(Class clazz);参数指的是要查询的字节码 
  29.  *         添加条件的方法: 
  30.  *              Criteria的add方法。 
  31.  *         添加条件涉及的对象: 
  32.  *             Restrictions 
  33.  * 
  34.  * @author Switch 
  35.  */  
  36. public class TestQBCQuery {  
  37.     /** 
  38.      * 基本查询:查询所有 
  39.      * 
  40.      * 需求: 
  41.      *     查询所有客户 
  42.      */  
  43.     @Test  
  44.     public void test1(){  
  45.         Session session = HibernateUtils.getCurrentSession();  
  46.         Transaction tx = session.beginTransaction();  
  47.         //1.获取Criteria对象  
  48.         Criteria criteria = session.createCriteria(Customer.class);  
  49.         //2.执行list方法,得到结果集  
  50.         @SuppressWarnings("unchecked")  
  51.         List<Customer> customers = criteria.list();  
  52.         tx.commit();  
  53.         for (Customer customer : customers) {  
  54.             System.out.println(customer);  
  55.         }  
  56.     }  
  57.   
  58.     /** 
  59.      * 条件查询 
  60.      *     需求:查询客户级别是23的,客户名称带有集字的 
  61.      */  
  62.     @Test  
  63.     public void test2(){  
  64.         Session session = HibernateUtils.getCurrentSession();  
  65.         Transaction tx = session.beginTransaction();  
  66.         //1.获取Criteria对象  
  67.         Criteria criteria = session.createCriteria(Customer.class);  
  68.         // 添加条件  
  69.         criteria.add(Restrictions.eq("custLevel""23"));  
  70.         criteria.add(Restrictions.like("custName""%集%"));  
  71.         //2.执行list方法,得到结果集  
  72.         @SuppressWarnings("unchecked")  
  73.         List<Customer> customers = criteria.list();  
  74.         tx.commit();  
  75.         for (Customer customer : customers) {  
  76.             System.out.println(customer);  
  77.         }  
  78.     }  
  79.   
  80.     /** 
  81.      * 分页查询 
  82.      * 
  83.      * 涉及的方法: 
  84.      *         setFirstResult(int firstResult); 
  85.      *         setMaxResults(int maxResults); 
  86.      * 含义和HQL是一模一样的 
  87.      */  
  88.     @Test  
  89.     public void test3(){  
  90.         Session session = HibernateUtils.getCurrentSession();  
  91.         Transaction tx = session.beginTransaction();  
  92.         //1.获取Criteria对象  
  93.         Criteria criteria = session.createCriteria(Customer.class);  
  94.         criteria.setFirstResult(0);  
  95.         criteria.setMaxResults(2);  
  96.         //2.执行list方法,得到结果集  
  97.         @SuppressWarnings("unchecked")  
  98.         List<Customer> customers = criteria.list();  
  99.         tx.commit();  
  100.         for (Customer customer : customers) {  
  101.             System.out.println(customer);  
  102.         }  
  103.     }  
  104.   
  105.     /** 
  106.      * 统计查询: 
  107.      *      使用QBC来添加聚合函数 
  108.      * 
  109.      * count() avg() min() max() sum() 
  110.      * 
  111.      * 涉及的方法: 
  112.      *         setProjections(Projection p ); 它可以加查询语句的结构。 
  113.      * 涉及的类: 
  114.      *         Projections 
  115.      *         该类中提供了一些静态方法 
  116.      */  
  117.     @Test  
  118.     public void test4(){  
  119.         Session session = HibernateUtils.getCurrentSession();  
  120.         Transaction tx = session.beginTransaction();  
  121.         //1.获取Criteria对象  
  122.         Criteria criteria = session.createCriteria(Customer.class);  
  123.         criteria.setProjection(Projections.count("custId"));  
  124.   
  125.         //2.执行uniqueResult方法,得到结果  
  126.         Long result = (Long) criteria.uniqueResult();  
  127.         tx.commit();  
  128.   
  129.         System.out.println(result);  
  130.     }  
  131.   
  132.     /** 
  133.      * 排序查询 
  134.      * 
  135.      * 涉及方法: 
  136.      *       Criteria的addOrder方法。该方法需要一个Order对象作为参数 
  137.      * Order对象有两个方法: 
  138.      *         desc(String propertyName):按照指定的属性名称,倒序排序。 
  139.      *         asc(String propertyName):按照自顶的属性名称,正序排序。 
  140.      */  
  141.     @Test  
  142.     public void test5(){  
  143.         Session session = HibernateUtils.getCurrentSession();  
  144.         Transaction tx = session.beginTransaction();  
  145.         //1.获取Criteria对象  
  146.         Criteria criteria = session.createCriteria(LinkMan.class);  
  147.         criteria.addOrder(Order.desc("lkmId"));  
  148.   
  149.         //2.执行list方法,得到结果集  
  150.         @SuppressWarnings("unchecked")  
  151.         List<LinkMan> linkMans = criteria.list();  
  152.   
  153.         tx.commit();  
  154.         for (LinkMan linkMan : linkMans) {  
  155.             System.out.println(linkMan);  
  156.         }  
  157.     }  
  158.   
  159.   
  160.     /** 
  161.      * 离线查询: 
  162.      *      在线对象: 
  163.      *         Criteria对象。它的获取必须要一个可用的Session来创建。如果Session不能用,则不能创建Criteria。 
  164.      *         我们使用Criteria进行的查询就是在线查询。 
  165.      *      离线对象: 
  166.      *         创建DetachedCriteria不需要一个可用的Session。 
  167.      *         用DetachedCriteria进行的查询就叫做离线查询 
  168.      * 涉及的对象 
  169.      *         DetachedCriteria 
  170.      * 如何获取 
  171.      *         DetachedCriteria.forClass(Class clazz);参数的含义:要查询的实体类 
  172.      * 如何设置查询条件: 
  173.      *         和Criteria是一样的 
  174.      * 
  175.      * 在实际开发中:多条件查询用此种方式 
  176.      */  
  177.   
  178.     //Servlet的方法  
  179.     @Test  
  180.     public void doGet(){  
  181.         //1.获取请求参数  
  182.         String custLevel = "23";  
  183.         String custName = "集";  
  184.         //2.查询所有客户  
  185.         DetachedCriteria dCriteria = DetachedCriteria.forClass(Customer.class);  
  186.         dCriteria.add(Restrictions.eq("custLevel", custLevel));  
  187.         dCriteria.add(Restrictions.like("custName""%"+custName+"%"));  
  188.   
  189.         List<Customer> cs = servicefindAllCustomer(dCriteria);  
  190.   
  191.         for(Customer c : cs){  
  192.             //3.存入请求域中  
  193.             //4.转向列表页面  
  194.             System.out.println(c);  
  195.         }  
  196.     }  
  197.   
  198.     //Service的方法  
  199.     public List<Customer> servicefindAllCustomer(DetachedCriteria dCriteria){  
  200.         return daofindAllCustomer(dCriteria);  
  201.     }  
  202.   
  203.     //Dao中的方法  
  204.     public List<Customer> daofindAllCustomer(DetachedCriteria dCriteria){  
  205.         Session s = HibernateUtils.getCurrentSession();  
  206.         Transaction tx = s.beginTransaction();  
  207.         //1.把离线对象激活  
  208.         Criteria c = dCriteria.getExecutableCriteria(s);  
  209.         //3.执行list方法,得到结果集  
  210.         @SuppressWarnings("unchecked")  
  211.         List<Customer> list = c.list();  
  212.         tx.commit();  
  213.         return list;  
  214.     }  
  215. }  


原生SQL查询
     采用HQL或QBC检索方式时,Hibernate生成标准的SQL查询语句,适用于所有的数据库平台,因此这两种检索方式都是跨平台的。但有的应用程序可能需要根据底层数据库的SQL方言,来生成一些特殊的查询语句。在这种情况下,可以利用Hibemate提供的原生SQL检索方式 。
     原生SQL查询时通过SQLQuery sqlQuery = session.createSQLQuery(String sql)来实现的,因为操作方式就是SQL语句,故不再介绍。
[java] view plain copy
  1. /** 
  2.  * SQLQuery 它使用的是原始的SQL语句查询 
  3.  */  
  4. @Test  
  5. public void test3() {  
  6.     Session s = HibernateUtils.getCurrentSession();  
  7.     Transaction tx = s.beginTransaction();  
  8.     // 1.获取SQLQuery对象  
  9.     SQLQuery sqlquery = s.createSQLQuery("select * from cst_customer");// 参数是SQL语句  
  10.     // 2.执行sqlquery的方法,返回结果集  
  11.     /* 
  12.      * List<Object[]> list = sqlquery.list(); for(Object[] os : list){ 
  13.      * System.out.println( 
  14.      * "-------------每出现一行分割线,表示外层循环执行了一次-------------------"); <br/> 
  15.      * for(Object o : os){ System.out.println(o); } } 
  16.      */  
  17.     // 添加实体类字节码,把查询结果转成实体类对象  
  18.     sqlquery.addEntity(Customer.class);  
  19.     List<Customer> cs = sqlquery.list();  
  20.     for (Customer c : cs) {  
  21.         System.out.println(c);  
  22.     }  
  23.     tx.commit();  
  24. }  



该博文使用的Hibernate配置文件和映射文件


Customer.hbm.xml
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC  
  3.   
  4.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  5.     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
  6. <!--  
  7. 1、导入dtd约束  
  8.      在Hibernate的核心jar包中:hibernate-mapping-3.0.dtd  
  9. 2、编写配置文件  
  10.           实体类和数据库表的对应关系  
  11.           实体类中属性和表的字段的对应关系  
  12.  -->  
  13. <hibernate-mapping package="com.pc.hibernate.domain">  
  14.      <!-- class标签:  
  15.               作用:用于配置实体类和表之间的对应关系  
  16.               属性:  
  17.                    name:实体类的名称。它应该写全限定类名  
  18.                    table:数据库表的名称  
  19.      -->  
  20.      <class name="Customer" table="cst_customer" lazy="true" batch-size="3">  
  21.           <!-- id标签:  
  22.                    作用:映射主键  
  23.                    属性:  
  24.                         name:实体类的属性名称  
  25.                         column:数据库表的字段名称  
  26.                         type:主键的类型  
  27.           -->  
  28.           <id name="custId" column="cust_id" type="java.lang.Long">  
  29.               <!-- generator标签:  
  30.                         作用:主键的生成方式  
  31.                         属性:  
  32.                              class:指定方式  
  33.                              取值:native  
  34.                                   含义:使用本地数据库的自动增长能力。  
  35.               -->  
  36.   
  37.               <generator class="native"/>  
  38.           </id>  
  39.           <!-- property标签:  
  40.                    作用:映射其他字段  
  41.                    属性:  
  42.                         name:实体类的属性名称  
  43.                         column:数据库表的字段名称  
  44.                         type:字段的类型  
  45.                         length:数据库中对应列的长度  
  46.           -->  
  47.           <property name="custName" column="cust_name" type="java.lang.String" length="32"/>  
  48.           <property name="custSource" column="cust_source" type="java.lang.String" length="32"/>  
  49.           <property name="custIndustry" column="cust_industry" type="java.lang.String" length="32"/>  
  50.           <property name="custLevel" column="cust_level" type="java.lang.String" length="32"/>  
  51.           <property name="custAddress" column="cust_address" type="java.lang.String" length="128"/>  
  52.           <property name="custPhone" column="cust_phone" type="java.lang.String" length="64"/>  
  53.   
  54.           <!-- 配置一对多 -->  
  55.           <set name="linkMans" inverse="false" cascade="save-update" batch-size="4" lazy="true" fetch="select">  
  56.               <key column="lkm_cust_id" />  
  57.               <one-to-many class="LinkMan"/>  
  58.           </set>  
  59.      </class>  
  60. </hibernate-mapping>  


LinkMan.hbm.xml
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC  
  3.   
  4.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  5.     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">  
  6. <hibernate-mapping package="com.pc.hibernate.domain">  
  7.      <class name="LinkMan" table="cst_linkman">  
  8.           <id name="lkmId" column="lkm_id" type="java.lang.Long">  
  9.               <generator class="native" />  
  10.           </id>  
  11.           <property name="lkmName" column="lkm_name" type="java.lang.String" length="16"/>  
  12.           <property name="lkmGender" column="lkm_gender" type="java.lang.String" length="10"/>  
  13.           <property name="lkmPhone" column="lkm_phone" type="java.lang.String" length="16"/>  
  14.           <property name="lkmMobile" column="lkm_mobile" type="java.lang.String" length="16"/>  
  15.           <property name="lkmEmail" column="lkm_email" type="java.lang.String" length="64"/>  
  16.           <property name="lkmPosition" column="lkm_position" type="java.lang.String" length="16"/>  
  17.           <property name="lkmMemo" column="lkm_memo" type="java.lang.String" length="512"/>  
  18.   
  19.           <!-- 配置多对一 -->  
  20.           <many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="save-update" lazy="proxy" fetch="select"/>  
  21.      </class>  
  22. </hibernate-mapping>  

hibernate.cfg.xml
[html] view plain copy
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE hibernate-configuration PUBLIC  
  3.      "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
  4.      "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">  
  5. <!-- 1、导入dtd约束 在hibernate核心jar包中:hibernate-configuration-3.0.dtd 2、编写配置文件 -->  
  6. <hibernate-configuration>  
  7.      <!-- 配置SessionFactory -->  
  8.      <!-- 创建SessionFactory需要3部分信息。 而配置文件中要写哪些配置,我们可以翻阅资料。 -->  
  9.      <!-- 第一部分:连接数据库的基本信息,第二部分:hibernate的基本配置,第三部分:映射文件的位置 -->  
  10.      <session-factory>  
  11.           <!-- 1、连接数据库的基本信息 -->  
  12.           <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>  
  13.           <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mycrm</property>  
  14.           <property name="hibernate.connection.username">root</property>  
  15.           <property name="hibernate.connection.password">123456</property>  
  16.   
  17.           <!-- 数据库的方言 -->  
  18.           <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>  
  19.   
  20.           <!-- 2、hibernate的基本配置 -->  
  21.           <!-- 是否显示SQL语句 -->  
  22.           <property name="hibernate.show_sql">true</property>  
  23.           <!-- 是否格式化显示SQL语句 -->  
  24.           <!-- <property name="hibernate.format_sql">true</property> -->  
  25.           <!-- 采用何种策略来创建表结构: -->  
  26.           <!-- update:检查表结构和实体类映射文件的变化,如果发现映射文件和表结构不一致,更新表结构。 -->  
  27.           <!-- 注意:hibernate不能创建数据库,只能在有数据库的情况下创建表结构。 -->  
  28.           <property name="hibernate.hbm2ddl.auto">update</property>  
  29.   
  30.           <!-- 配置hibernate使用连接池:告知Hibernate使用连接池的厂商 -->  
  31.           <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property>  
  32.   
  33.           <!-- 配置把Session绑定到当前线程上,从而保证一个线程只有一个Session -->  
  34.           <property name="hibernate.current_session_context_class">thread</property>  
  35.   
  36.           <!-- 3、映射文件的位置 -->  
  37.           <mapping resource="com/pc/hibernate/domain/Customer.hbm.xml" />  
  38.           <mapping resource="com/pc/hibernate/domain/LinkMan.hbm.xml" />  
  39.      </session-factory>  
  40. </hibernate-configuration>