hibernate整理

Hibernate是一个开源的对象关系映射框架,它对JDBC进行了轻量级的对象封装,使Java程序员可以随心所欲的使用对象编程思维来操纵数据库

提供了从java类到数据库表之间的映射,也提供了数据查询和恢复机制。相对于使用JDBC和SQL来手工操作数据库,Hibernate可以大大减少


2. Hibernate原理:

     Hibernate技术本质上是一个提供数据库服务的中间件。Hibernate的工作原理,他是利用数据库以及其他一些配置文件如:hibernate.cfg.xml,

xxx.hbm.xml等来为应用程序提供数据持久化服务的。

  1.   Configuration来读取hibernate.cfg.xml文件
  2.   使用Configuration对象创建SessionFactory
  3.   用SessionFactory来打开一个Session
  4.   创建事务Transaction
  5.   begin事务
  6.   使用Session进行数据库操作
  7.   关闭或回滚事务
  8.   关闭Session

3.2 先创建一个User实体

package com.a_helloworld;
 2 
 3 public class User {
 4 
 5     private int id;
 6     private String name;
 7     public int getId() {
 8         return id;
 9     }
10     public void setId(int id) {
11         this.id = id;
12     }
2425     
26 }

3.4 简单配置hibernate.cfg.xml配置文件,这个文件名可以随便修改(xxx.cfg.xml),但是没多大意义,一般不建议修改。配置的信息如下:


 1 <!DOCTYPE hibernate-configuration PUBLIC
 2     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 3     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 4 
 5 <hibernate-configuration>
 6     <session-factory name="foo">
 7     
 8         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 9         <property name="connection.username">root</property>
10         <property name="connection.password">123456</property>
11         <property name="connection.url">jdbc:mysql:///user</property>
12         
13         <!-- 要根据自己使用的数据库来配置相对应的属性,也成方言,针对不同数据库
14              关于怎么配置可以查看HibernateAPI
15          -->
16         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
17         
18         <!-- Hibernate 創建的SQL語句会显示在控制台 -->
19         <property name="hibernate.show_sql">true</property>
20         
21         <!-- 选择方案,常用值:validate | update | create | create-drop -->
22         <property name="hbm2ddl.auto">update</property>
23         
24         <mapping resource="com/a_helloworld/user.hbm.xml"/> -- 导入实体映射配置,程序每次启动都会自动检索
25         
26     </session-factory>
27 </hibernate-configuration>

Hibernate get和load区别

get和load方式是根据id取得一个记录

下边详细说一下get和load的不同,因为有些时候为了对比也会把find加进来。

1.从返回结果上对比:
load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常
get方法检索不到的话会返回null

2.从检索执行机制上对比:

get方法和find方法都是直接从数据库中检索,而load方法执行比较复杂先查找session的persistent Context 中是否有缓存,如果有则直接

返回,如果没有判断是够shilazy,如果不是直接访问数据库检索,查询记录返回,查不到,如果是lazy则需要建立代理对象,对象的initiaized

属性为false,target属性为null,在范文获得的代理了对象的属性时,检索数据库,如果找到记录则吧记录的对象复制到代理对象的target上,

并将initialized=true,如果找不到就跑出异常。

3.根本区别说明

如果你使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的,所以它可以放心的使用,它可以放心的使用代理来 延迟加载该对象。数据库中不存在该数据时抛异常,而不是在创建这个对象时(注意:这就是由于“延迟加载”在作怪)。

对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null。

4.简单总结

总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,只能抛异常;而对于get方法,hibernate一定要获取到真实的数据,否则返回null。

Hibernate的一级和二级缓存

  1. 管理session
session对象的生命周期与本地线程绑定
<!-- 配置session对象的生命周期和本地线程绑定 -->

<property name=”hibernate.current_session_context_class”>thread</property>

2. hibernate缓存机制
Hibernate中提供了两个级别的缓存
第一级别的缓存是 Session的缓存,它是属于线程范围的缓存。这一级别的缓存由 hibernate 管理的,我们无需干预
第二级别的缓存是 SessionFactory的缓存,它是属于进程范围的缓存

缓存的作用主要用来提高性能,可以简单的理解成一个Map

使用缓存涉及到三个操作:把数据放入缓存、从缓存中获取数据、删除缓存中的无效数据

一级缓存:

一级缓存指的是session对象的一个hashMap(session的实现类是:sessionImpl)

用户不需要做任何配置就可以使用,他的生命周期小只要session关闭,缓存就消失每个session拥有自己的缓存去执行session.save()

操作的时候,会先放到一级缓存----》放到的对象成为持久化对象

* 执行查询的时候,会先到session的一级缓存中查找 
          * 如果找到,直接从缓存中获取该对象,这时不再查询数据库
          * 如果没有找到,此时查询数据库,产生select语句,并把查询到的对象放入缓存

Customer c1 = (Customer) session.get(Customer.class, 1);

// 根据id查询一个Customer对象

// 根据业务来编写代码

// Customer c = session.get(Customer.class, 1);

Customer c = session.load(Customer.class, 1);

OID检索方式:

  1.  Customer customer = session.load(Customer.class, 1L);  
  2.         transaction.commit();  
  3.         // 输出1和报错could not initialize proxy - no Session  
  4.         // 当<class name="Customer" table="cst_customer" lazy="false">时  
  5.         // 该方法正确,因为这时候已经不延迟加载了  
  6.         System.out.println(customer.getCustId()); 

对象导航查询:

  对象图导航检索方式是根据己经加载的对象,导航到他的关联对象 。它利用类与类之间的关系来检索对象 。

譬如要查找一个联系人对应的客户,就可以由联系人对象自动导航找到联系人所属的客户对象。

当然,前提是必须在对象关系映射文件上配置了多对一的关系

  1. /** 
  2.      * 根据客户id查询联系人信息 
  3.      * @param custId 
  4.      * @return 
  5.      */  
  6.     public List<LinkMan> findLinkManByCid(Long custId){  
  7.         Session s = HibernateUtils.getCurrentSession();  
  8.         Transaction tx = s.beginTransaction();  
  9.         SQLQuery query = s.createSQLQuery("select * from cst_linkman where lkm_cust_id = ? ");  
  10.         query.setLong(0, custId);  
  11.         query.addEntity(LinkMan.class);  
  12.         @SuppressWarnings("unchecked")  
  13.         List<LinkMan> mans = query.list();  
  14.         tx.commit();  
  15.         return mans;  
  16.     }  

  1.   /** 
  2.      * 需求: 
  3.      *     查询id为1的客户下的所有联系人 
  4.      */  
  5.     @Test  
  6.     public void test1(){  
  7.         // 传统的使用方式  
  8.         List<LinkMan> list = findLinkManByCid(1L);  
  9.         System.out.println(list);  
  10.   
  11.         Customer c = findById(1L);  
  12.         //对象导航查询  
  13.         // 需要将Customer上对应于LinkMan的关系检索策略的懒加载关闭  
  14.         Set<LinkMan> linkmans = c.getLinkMans();  
  15.         for(LinkMan linkMan : linkmans){  
  16.             System.out.println(linkMan);  
  17.         }  
  18.     }  

HQL查询

 HQL (Hibernate Query Language ) 是面向对象的查询语言,它和 SQL 查询语言有些相似 ,

但它使用的是类、对象和属性的概念 ,而没有表和字段的概念

在Hibernate提供的各种检索方式中 ,HQL是官方推荐的查询语言,也是使用最广泛的一种检索 方式。

 涉及的对象:
          Query
     如何获取Query:
          session.createQuery(String hql);
     HQL语句写法:
           表名用实体类名称替代
字段名用实体类属性名称(get/set方法后面的部分,并且把首字母转小写)

  1. /** 
  2.      * 条件查询: 
  3.      *     需求: 
  4.      *         查询客户级别是23的,客户名称带有 集 字的 
  5.      *  给HQL语句加条件用where 
  6.      *  HQL语句的参数占位符也可以使用? 
  7.      *  hibernate中,参数占位符是从0开始的。 
  8.      */  
  9.     @Test  
  10.     public void test2(){  
  11.         Session session = HibernateUtils.openSession();  
  12.         Transaction transaction = session.beginTransaction();  
  13.         // 查询客户级别是23的,客户名称带有 集 字的  
  14.         Query query = session.createQuery("from Customer where custLevel = ? and custName like ?");  
  15.         query.setString(0"23");  
  16.         query.setString(1"%集%");  
  17.         @SuppressWarnings("unchecked")  
  18.         List<Customer> customers = query.list();  
  19.         transaction.commit();  
  20.         for (Customer customer : customers) {  
  21.             System.out.println(customer);  
  22.         }  
  23.     }  
  1.   /** 
  2.      * 投影查询: 
  3.      *      当我们查询实体对象时,并不需要所有字段信息,只查询部分,但是还想让他成为一个实体对象。其实就是用部分字段来投影出整个实体对象。 
  4.      * 使用要求: 
  5.      *     HQL语句: 
  6.      *         写法必须是  new 实体类名称(查询的字段) 
  7.      *         select new Customer(custId,custName) from Customer 
  8.      *         注意:如果你的实体类在工程中唯一,则可以直接写类名。如果实体类在工程中不唯一,需要写全限定类名。 
  9.      *  实体类要求: 
  10.      *      必须在实体类中提供一个相同参数列表的构造函数。 
  11.      *          
  12.      */  
  13.     @Test  
  14.     public void test71(){  
  15.         Session session = HibernateUtils.getCurrentSession();  
  16.         Transaction transaction = session.beginTransaction();  
  17.         // 只获取客户的ID和名字,并封装成客户对象  
  18.         Query query = session.createQuery("select new Customer(custId, custName) from Customer");  
  19.         @SuppressWarnings("unchecked")  
  20.         List<Customer> customers = query.list();  
  21.         transaction.commit();  
  22.         for (Customer customer : customers) {  
  23.             System.out.println(customer.getCustId() + " " + customer.getCustName());  
  24.         }  
  25.     }  
  1.   /** 
  2.      * 左外连接查询和迫切左外连接查询的区别 
  3.      * 区别: 
  4.      *     返回的结果集不一样。在实际开发中用的不多,此处讲解就是为了说明他们之间的区别 
  5.      * 注意: 
  6.      *     Hibernate中没有右外连接 
  7.      * 
  8.      * Hibernate左外连接返回的数据:    
  9.      *         返回的是一个有Object数组组成的List集合,该数组中有两个对象。一个是主表实体,一个是从表实体。 
  10.      *         主表实体有可能重复 
  11.      */  
  12.     //左外连接查询  
  13.     @Test  
  14.     public void test81(){  
  15.         Session session = HibernateUtils.getCurrentSession();  
  16.         Transaction transaction = session.beginTransaction();  
  17.         //1.获取Query对象  
  18.         //sql语句的左外:select * from cst_customer c left outer join cst_linkman l on c.cust_id = l.lkm_cust_id;  
  19.         Query query = session.createQuery("from Customer c left join c.linkMans");  
  20.         //2.执行query对象的方法  
  21.         @SuppressWarnings("unchecked")  
  22.         List<Object[]> list = query.list();  
  23.         transaction.commit();  
  24.         for (Object[] objects : list) {  
  25.             System.out.println("------一组对象-------");  
  26.             for (Object object : objects) {  
  27.                 System.out.println(object);  
  28.             }  
  29.         }  
  30.     }  

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完成查询。
  1.  Hibernate中的查询方式: 
  2.  *         QBC查询: 
  3.  *             Query By Criteria  它是一种更加面向对象的查询方式。 
  4.  *             它把查询条件都用方法封装了。里面的参数全都需要使用实体类的属性名称。 
  5.  *         涉及的对象: 
  6.  *             Criteria 
  7.  *             DetachedCriteria 
  8.  *         获取的方式: 
  9.  *             session.createCriteria(Class clazz);参数指的是要查询的字节码 
  10.  *         添加条件的方法: 
  11.  *              Criteria的add方法。 
  12.  *         添加条件涉及的对象: 
  13.  *             Restrictions 
  1.    /** 
  2.      * 条件查询 
  3.      *     需求:查询客户级别是23的,客户名称带有集字的 
  4.      */  
  5.     @Test  
  6.     public void test2(){  
  7.         Session session = HibernateUtils.getCurrentSession();  
  8.         Transaction tx = session.beginTransaction();  
  9.         //1.获取Criteria对象  
  10.         Criteria criteria = session.createCriteria(Customer.class);  
  11.         // 添加条件  
  12.         criteria.add(Restrictions.eq("custLevel""23"));  
  13.         criteria.add(Restrictions.like("custName""%集%"));  
  14.         //2.执行list方法,得到结果集  
  15.         @SuppressWarnings("unchecked")  
  16.         List<Customer> customers = criteria.list();  
  17.         tx.commit();  
  18.         for (Customer customer : customers) {  
  19.             System.out.println(customer);  
  20.         }  
  21.     }  
  1.  /** 
  2.      * 离线查询: 
  3.      *      在线对象: 
  4.      *         Criteria对象。它的获取必须要一个可用的Session来创建。如果Session不能用,则不能创建Criteria。 
  5.      *         我们使用Criteria进行的查询就是在线查询。 
  6.      *      离线对象: 
  7.      *         创建DetachedCriteria不需要一个可用的Session。 
  8.      *         用DetachedCriteria进行的查询就叫做离线查询 
  9.      * 涉及的对象 
  10.      *         DetachedCriteria 
  11.      * 如何获取 
  12.      *         DetachedCriteria.forClass(Class clazz);参数的含义:要查询的实体类 
  13.      * 如何设置查询条件: 
  14.      *         和Criteria是一样的 
  15.      * 
  16.      * 在实际开发中:多条件查询用此种方式 
  17.      */  
  18.   
  19.     //Servlet的方法  
  20.     @Test  
  21.     public void doGet(){  
  22.         //1.获取请求参数  
  23.         String custLevel = "23";  
  24.         String custName = "集";  
  25.         //2.查询所有客户  
  26.         DetachedCriteria dCriteria = DetachedCriteria.forClass(Customer.class);  
  27.         dCriteria.add(Restrictions.eq("custLevel", custLevel));  
  28.         dCriteria.add(Restrictions.like("custName""%"+custName+"%"));  
  29.   
  30.         List<Customer> cs = servicefindAllCustomer(dCriteria);  
  31.   
  32.         for(Customer c : cs){  
  33.             //3.存入请求域中  
  34.             //4.转向列表页面  
  35.             System.out.println(c);  
  36.         }  
  37.     }  
  38.   
  39.     //Service的方法  
  40.     public List<Customer> servicefindAllCustomer(DetachedCriteria dCriteria){  
  41.         return daofindAllCustomer(dCriteria);  
  42.     }  
  43.   
  44.     //Dao中的方法  
  45.     public List<Customer> daofindAllCustomer(DetachedCriteria dCriteria){  
  46.         Session s = HibernateUtils.getCurrentSession();  
  47.         Transaction tx = s.beginTransaction();  
  48.         //1.把离线对象激活  
  49.         Criteria c = dCriteria.getExecutableCriteria(s);  
  50.         //3.执行list方法,得到结果集  
  51.         @SuppressWarnings("unchecked")  
  52.         List<Customer> list = c.list();  
  53.         tx.commit();  
  54.         return list;  
  55.     }  
  56. }  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值