Hibernate原理分析
1.整体架构
Criteria是一种比hql更面向对象的查询方式。Criteria 可使用 Criterion 和 Projection 设置查询条件。可以设置 FetchMode( 联合查询抓取的模式 ) ,设置排序方式,Criteria 还可以设置 FlushModel (冲刷 Session 的方式)和 LockMode (数据库锁模式)。
ANTLR—Another Tool for Language Recognition,是一个开源语法分析器,其前身是PCCTS,它为包括Java,C++,C#在内的语言提供了一个通过语法描述来自动构造自定义语言的识别器(recognizer),编译器(parser)和解释器(translator)的框架。ANTLR可以通过断言(Predicate)解决识别冲突;支持动作(Action)和返回值(Return Value)来;更棒的是,它可以根据输入自动生成语法树并可视化的显示出来。由此,计算机语言的翻译变成了一项普通的任务。
2.流程:
Configuration cfg = Configuration.configure();
SessionFactory sf = cfg.buildSessionFactory();
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
tx.commit();
s.close();
3.对象的状态
*临时状态 (transient)
1】不处于Session 缓存中
2】数据库中没有对象记录
Java如何进入临时状态
1】通过new语句刚创建一个对象时
2】当调用Session 的delete()方法,从Session 缓存中删除一个对象时。
*持久化状态(persisted) :它拥有持久化标识((持久化标识可以认为映射表的主键),Hibernate保证任何持久化标识和数据库行标识的关系
1】处于Session 缓存中
2】持久化对象数据库中有对象记录
3】Session 在特定时刻会保持二者同步
Java如何进入持久化状态
1】Session 的save()把临时-》持久化状态
2】Session 的load(),get()方法返回的对象
3】Session 的find()返回的list集合中存放的对象
4】Session 的update(),saveOrupdate()使游离-》持久化
*游离状态(detached) :它也拥有持久化标识, 不保证和数据库的关联
1】不再位于Session 缓存中
2】游离对象由持久化状态转变而来,数据库中可能还有对应记录。
Java如何进入持久化状态-》游离状态
1】Session 的close()方法
2】Session 的evict()方法,从缓存中删除一个对象。提高性能。少用。
3个状态的实例:
为了方便,先创建一个管理Session的工具类HibernateUtils.java,代码如下:
1 package com.ysj.utils; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 7 8 public class HibernateUtils { 9 10 /** 11 * 创建静态块,用于初始化SessionFactory 12 */ 13 private static SessionFactory factory ; 14 static{ 15 try{ 16 // 默认获取src根目录下的 hibernate.cfg.xml配置文件 17 Configuration cfg = new Configuration().configure(); 18 // 通过配置文件获取 sessionFactory 19 factory = cfg.buildSessionFactory() ; 20 }catch(Exception e){ 21 e.printStackTrace() ; 22 } 23 } 24 25 /** 26 * 获得SessionFactory 27 */ 28 public static SessionFactory getSessionFactory(){ 29 return factory ; 30 } 31 32 /** 33 * 获得Session 34 */ 35 public static Session getSession(){ 36 if(factory != null){ 37 return factory.openSession() ; 38 }else{ 39 return null ; 40 } 41 } 42 43 /** 44 * 关闭Session 45 */ 46 public static void closeSession(Session session){ 47 if(session != null){ 48 if(session.isOpen()){ 49 session.close() ; 50 session = null ; 51 } 52 } 53 } 54 }
测试类SessionTest.java,代码如下:
1 package com.ysj; 2 3 import java.util.Date; 4 5 import junit.framework.TestCase; 6 7 import org.hibernate.Session; 8 import org.hibernate.Transaction; 9 10 import com.ysj.utils.HibernateUtils; 11 12 public class SessionTest extends TestCase { 13 14 /** 15 * 持久化对象生命周期的过程演示 16 */ 17 public void testSave(){ 18 Session session = null ; 19 Transaction tran = null ; 20 User user = null ; 21 try{ 22 session = HibernateUtils.getSession() ; 23 tran = session.beginTransaction() ; 24 /** 25 * Transient(瞬态) : 26 * 1、在数据库中没有与之匹配的数据; 27 * 2、没有纳入session的管理; 28 * 3、如果在瞬态session 调用了 save()等方法就变为了持久态; 29 */ 30 user = new User() ; 31 user.setName("小一") ; 32 user.setPassword("xiaoyi") ; 33 user.setCreateTime(new Date()) ; 34 user.setExpireTime(new Date()) ; 35 /** 36 * Persistent(持久态) : 37 * 1、persistent状态的对象在数据库中有与之匹配的数据; 38 * 2、纳入了session的管理; 39 * 3、在清理缓存(脏数据检查)的时候,会和数据库同步; 40 * 4、在session关闭后,在持久态里面的内容,变为托管态,数据如果修改不会影响数据库对应值; 41 */ 42 session.save(user); 43 44 user.setName("小二"); 45 /* 46 * 注意 : 47 * 在执行完tran.commit()方法后,会在控制台输出两条SQL语句,分别是 48 * Hibernate: insert into t_user (name, password, createTime, expireTime, id) values (?, ?, ?, ?, ?) 49 * Hibernate: update t_user set name=?, password=?, createTime=?, expireTime=? where id=? 50 * 51 * session.save(user); // 执行到save()方法时插入数据库一条记录。 52 * user.setName("小二"); // 当对持久态对象进行修改时,会执行update操作。相当于在该条词句下面显示执行session.update(user);操作。 53 */ 54 tran.commit() ; 55 56 }catch(Exception e){ 57 if(tran != null){ 58 tran.rollback() ; 59 } 60 e.printStackTrace() ; 61 }finally{ 62 HibernateUtils.closeSession(session); 63 } 64 /** 65 * Detached(托管态) : 66 * 1、在数据库中有与之匹配的数据; 67 * 2、没有纳入session的管理; 68 * 3、托管态对象中有主键值,瞬态的id没有主键值 69 */ 70 user.setName("小三") ; 71 try{ 72 session = HibernateUtils.getSession() ; 73 session.beginTransaction() ; 74 /* 75 * 将detached对象重新纳入session管理,此时将变为persistent状态的对象。 76 * persistent状态的对象,在清理缓存时会和数据库同步。 77 */ 78 session.update(user); 79 session.getTransaction().commit() ; 80 }catch(Exception e){ 81 session.getTransaction().rollback(); 82 e.printStackTrace(); 83 }finally{ 84 HibernateUtils.closeSession(session); 85 } 86 } 87 }
4.反射运用
每次开发项目时,在做数据库开发时,对于不同类都有对应的Dao类,这就要要编写大量的Dao类,其中大多是代码堆砌,但有时我们要完成特定的操作,开发独立的Dao类是必须的,但如果只是实现数据的插入、读取、更新、删除,那么如果有一个通用的Dao类可以对数据库中的所有表进行操作,可以免去编写大量同质代码的负担。
Reflection是Java被视为动态语言的一个关键性质,这个机制允许程序在运行时通过Reflection APIs却任何一个一直名称的的class的内部信息,包括modifiers、superclass、实现的interfaces、fields和methods等所有信息,并可于运行时改变fields内容和调用methods。
1)在运行时判断人一个对象所属的类(在插入一个类时,判断他属于哪张表,哪个配置XML)
2)在运行是构造任意一个类的对象(查询时,获取数据库中的数据后,构建出目标类来)
3)在运行时判断任意一个类所具有的成员变量和方法
4)在运行时调用任意一个对象的方法(判断一个类有什么方法,才能在插入时get,查询时set)
利用Java的反射机制就可以解决之前必须对知道每个类的属性和方法来调用的问题。
5.动态代理
Hibernate主要用了CGLIB和javassist。
主要是延迟加载使用了这个技术:
当 Hibernate 从数据库中初始化某个持久化实体时,该实体的关联实体属性是否随持久化类一起初始化呢?如果关联实体非常大,又不用马上调用它,没有必要一次加载所有的属性。所谓延迟加载就是等系统需要使用属性时才从数据库装载关联的数据。
public class Person { // 标识属性 private Integer id; // Person 的 name 属性 private String name; // 保留 Person 的 age 属性 private int age; // Family属性,是另一个表的属性 private Family family; // 下面省略了各属性的 setter 和 getter 方法 ... }
当Family属性特别大时,又不用马上访问,这时就用延迟加载。
当初始化一个Person实体时,没有去访问Family属性,此时 Person实体所关联的 Family实体并不是 Family对象,而是一个 Family_$$_javassist_0 类的实例,这个类是 Hibernate 使用 Javassist 项目动态生成的代理类——当 Hibernate 延迟加载关联实体时,将会采用 Javassist 生成一个动态代理对象,这个代理对象将负责代理“暂未加载”的关联实体(所以必须需要继承或接口)。
只要应用程序需要使用“暂未加载”的关联实体,Person_$$_javassist_0 代理对象会负责去加载真正的关联实体,并返回实际的关联实体——这就是最典型的代理模式。
6.缓存机制
缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能。缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。
缓存的范围
并发访问(类似数据库的隔离级别)
二级缓存
7.Hibernate和JDBC的异同
JDBC与Hibernate在性能上相比,JDBC灵活性有优势。而Hibernate在易学性,易用性上有些优势。当用到很多复杂的多表联查和复杂的数据库操作时,JDBC有优势。
相同点:
1两者都是java的数据库操作中的中间件
2.两者对于数据库进行直接操作的对象都不是线程安全的,都需要及时关闭。
3.两者都可以对数据库的更新操作进行显示的事务处理。
不同点:
1.使用的SQL语言不同:JDBC使用的是基于关系型数据库的标准SQL语言,Hibernate使用的是HQL语言。
2.操作的对象不同:JDBC操作的是数据将数据通过SQL语句直接传送到数据库中执行,Hibernate操作的是持久化数据,由Hibernate底层将持久化对象中的数据更新到数据库中。
3.数据状态不同:JDBC操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致,而Hibernate操作的数据是可持久化的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的。
参考:http://blog.sina.com.cn/s/blog_4b81125f010157rn.html
http://www.itzhai.com/hibernate-framework-structure-and-work-processes.html
http://blog.csdn.net/myyate/article/details/1932846
http://ysj5125094.iteye.com/blog/1897505
百科