以前做.net,最近做java项目,负责服务端的开发,直接用的jdbc,线程安全问题、缓存同步问题以及连接池什么的,都是手动写,不但麻烦而且容易出错。项目结束,赶快抽时间学了下hibernate,每天晚上写几个demo,一周下来,总算对hibernate有了一个整体的了解。
Hibernate作为一个orm框架,参考我最近的项目(加载的缓存比较多,即常用而又不需要修改的数据),hibernate提供的二级缓存机制让我看到了光明`(*∩_∩*)′,就从二级缓存说下我对hibernate的理解。
Hibernate二级缓存,简而言之,是SessionFactory级别的缓存。什么意思?明白了SessionFactory是个什么东东,基本就明白了二级缓存的是个什么鬼。SessionFactory,创建Session的工厂,我们都知道Session是干嘛的,那如果我们来设计一个orm,那怎么设计SessionFactory呢?当然,SessionFactory要加载数据库连接配置、数据对象元数据,这两项是必不可少的,如果SessionFactoy不知道数据库连接字符串,还谈什么orm呢,所以说,SessionFactory是Hibernate的出发点,它加载了一切初始化配置,而且一旦加载不允许修改,从这里可以明白SessionFactory是线程安全的,再多的线程共享其数据也不会出问题,不能修改决定了这一点。一般一个应用程序在启动之时,会创建一个单例的SessionFactory,至于为什么,显而易见。二级缓存虽然是SessionFactory级别的,注意是属于其级别的,不属于SessionFactoy,因为Hibernate并没有实现它,而是采用其他缓存产品,比如ecache。什么数据适合放入二级缓存?这就要我们自己把握了,基本是一些常用且很久不修改的数据,一次加载就ok,避免频繁访问数据库。因为级别高,而且不修改(一般不修改,设置成read-only模式,read-write测试时用用就可以了),所以可以被众多的session共享之。
说了二级缓存,现在说一级缓存,何为一级缓存?在Hibernate中,一级缓存是指Session缓存,Session缓存是如何工作的呢?先从三个概念说起,Hibernate对象可以分为三种状态:瞬态(transient,也叫临时对象)、持久状态(persistent,也叫持久化对象)、游离状态(detached)。一个临时对象一般是new出来的,持久化对象一般从数据库get出来的,游离对象一般是被session抛弃的(evict)。session缓存是在这一个会话中,保持从数据库中取出来的数据,并随时同步,保证与数据库的数据一样。这就需要一个标识唯一标识这个对象是谁,这个标识就是Object-identifier(OID)。一个临时对象经过save、persit、saveOrUpdate会变成持久化对象,一个持久化对象通过evict、close、clear等会变成游离状态,一个游离对象通过update、saveOrupdate等也可以再变回持久化对象。当然各种方法都有其特定的使用条件和限制,有些地方需要注意,这里不再多说。总之,Session缓存,是Hibernate在一个会话之中实现的与数据库互通的策略机制,不管是延迟加载、事务提交flush等等都是为了更好的维护这个缓存机制,可以说,这个session机制是hibernate的灵魂所在。
Hibernate的关系映射包括一对多、一对一、多对多以及继承映射,当然可以双向映射。同样,这三个映射各有其特点,如果去记其映射方法,比如many-to-one、one-to-one等配置,不免落入下乘。可以站在设计者的角度来看,假如我们来设计一对多映射,怎么玩呢?首先“1”的一方如果需要的话,要维护一个集合吧;“n”的一方一定需要维护一个“1”方的对象吧,因为外键必然要设在n方。那映射文件就出来了,1方需要一个Set,而且要告诉他是哪个table,外键(key)是谁,对应的对象(one-to-many)是谁,再设置inverse=true把控制权交给多方,避免重复更新。多的一方,怎么才能找到1方的那个关联对象呢,首先要知道关联对象的类名吧(class),其次要知道哪一列吧(column)。当然还有一些cascade、cache等细节配置等等。以上只是简单总结下hiberate映射,知道它能干这事就ok,具体使用的时候肯定是要参考文档的。
Hibernate提供了三种查询方式:HQL、QBC、本地SQL。HQL是hibernate特有的类似sql查询的半面向对象的查询语言,只所以说他是半面向对象,是因为它参考了sql查询语言的方式,而HQL语法中,是对象化的,比如"from Employee where ename=:ename",这里的Employee不是表名,是类名,ename也不是数据库中的字段名而是对象属性名。QBC查询则是完全面向对象的,他通过一些静态类实现限定查询、统计查询、分页排序等。本地SQL查询,则是直接写标准的sql语句进行查询了。
最后,还有Sesison管理,hibernate基本提供了三种管理session的方式:线程绑定、jta事务管理、hibernate委托管理,只学习了一个线程绑定管理。线程绑定session,绑定的意思是一对一,一个线程对应一个session,所以不用考虑数据共享的问题,线程安全,另外还可以在同一个线程事务中对dao层的多个方法进行管理,方便!
学习重在总结思考,over.