1.持久化类编写规则java
Hibernate是持久化层的ORM映射框架,专一于数据的持久化工做。算法
持久化:所谓的持久化就是讲内存中的数据永久保存到关系型数据库中。数据库
持久化类:其实所谓的持久化类指的是一个Java类与数据库表创建了映射关系,那么这个类称为是持久化类。其实,你能够简单的理解为就是一个Java类,该类经过一个映射文件与数据库的表创建了关系。持久化类的编写规则以下:缓存
1.持久化类提供无参数构造:由于在hibernate的底层须要使用反射生成类的实例;
2.成员变量私有,提供共有get/set方法访问.需提供属性;由于Hibernate底层会将查询到的数据进行封装;
3.持久化类中的属性,应尽可能使用包装类型:由于包装类和基本数据类型的默认值不一样,包装类的类型语义描述更清晰,而基本数据类型不容易描述。举个例子:假设表中有一列员工工资,若是使用double类型,若是这个员工工资忘记录入到系统中,系统会将默认值0存入到数据库,若是这个员工工资被扣完了,也会在系统中存入0。那么这个0就有了多重含义,而若是使用包装类型就会避免以上状况,若是使用Double类型,忘记录入工资就会存入null,而这个员工工资被扣完了,就会存入0,不会产生歧义。
4.持久化类须要提供oid.与数据库中的主键列对应;由于hibernate中须要用过这个惟一的标识oid区分在内存中是不是同一个持久化类实例。在java中经过地址区分是不是同一个对象的,在关系型数据库的表中是经过主键区分是否同一条记录。那么hibernate就是经过这个oid来进行区分的。hibernate是不容许在内存中出现两个oid相同的持久化对象的。
5.不要用final修饰class:由于Hibernate中有延迟加载的机制,这个机制中会产生代理对象,hibernate产生代理对象使用的是字节码的加强技术完成的,其实就是产生了当前类的一个子类对象实现的。若是使用了final修饰持久化类,那么就不能产生子类,从而就不会产生代理对象,那么Hibernate的延迟加载策略(是一种优化手段)就会失效。(hibernate使用cglib代理生成代理对象.代理对象是继承被代理对象.若是被final修饰.将没法生成代理.)网络
持久化类咱们已经能够正常编写了,可是在持久化类中须要有一个惟一标识OID与表的主键去创建映射关系。并且主键通常咱们是不会让客户手动录入的,通常咱们是由程序生成主键。那么Hibernate中也提供了相应的主键生成的方式,那么咱们来看下hibernate的主键生成策略。session
2. Hibernate主键生成策略框架
主键的类型:在讲解Hibernate的主键生成策略以前,先来了解两个概念,即天然主键和代理主键,具体以下:ide
Hibernate提供了几个内置的主键生成策略,其经常使用主键生成策略的名称和描述以下:性能
3. Hibernate持久化对象的三种状态测试
了解了主键的生成策略以后,咱们能够进一步来了解持久化类了。hibernate为了更好地管理持久化类,特将持久化类分红了三种状态,分别是:瞬时态、持久态、托管态,一个持久化类的实例可能处于三种不一样状态中的某一种。
没有id,没有在session缓存中;瞬时态就称为临时态或者自由态,瞬时态的实例是由new命令建立、开辟内存空间的对象,不存在持久化标识oid(至关于主键值),还没有与hibernate Session关联,在数据库中也没有记录,失去引用后将被JVM回收。瞬时状态的对象在内存中是孤立存在的,与数据库中的数据无任何关联,仅是一个信息携带的载体。
有id,在session缓存中;持久态的对象存在持久化标识oid,加入到了Session缓存中,而且相关联的Session没有关闭,在数据库中有对应的记录,每条记录只对应惟一的持久化对象,须要注意的是,持久化对象是在事务还未提交前变成持久态的。
有id,没有在session缓存中;托管态也称离线态或者游离态,当某个持久化状态的实例与Session的关联被关闭时就变成了托管态。托管态对象存在持久化标识oid,而且仍然与数据库中的数据存在关联,只是失去了与当前Session的关联,托管状态对象发生改变时,hibernate不能检测到。
咱们以前已经介绍了持久化对象的三种状态了,其实咱们主要去研究持久太对象就够了,持久态对象其实有一个很是重要的特性:持久化对象能够自动更新数据库。
实例:
1. 编写测试代码
1 @Test 2 public void demo7() { 3 // 开启事务 4 Transaction tx = session.beginTransaction(); 5 // 得到持久化对象 6 Customer customer = session.get(Customer.class, 1l); 7 customer.setCust_name("nakelulu"); 8 // 不调用session.update(customer); 9 tx.commit(); 10 session.close(); 11 }
hibernate自动调用update方法。
4. hibernate的一级缓存
缓存是计算机领域很是通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其做用是下降应用程序直接读写永久性数据存储源的频率,从而提升应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质一般是内存。
Hibernate的缓存分为一级缓存和二级缓存,hibernate的这两级缓存都位于持久化层,存储的都是数据库数据的备份。其中第一级缓存为Hibernate的内置缓存,不能被卸载。
Hibernate的一级缓存就是指Session缓存,Session缓存是一块内存空间,用来存放相互管理的java对象,在使用Hibernate查询对象的时候,首先会使用对象属性的oid值在Hibernate的一级缓存中进行查找,若是找到匹配oid值得对象,就直接将该对象从一级缓存中取出使用,不会再查询数据库;若是没有找到相同oid值的对象,则会去数据库中查找相应的数据。
当从数据库中查询到所需的数据时,该数据信息也会放置到一级缓存中。Hibernate的一级缓存的做用就是减小对数据库的访问次数。
在Session接口的实现中包含一系列的Java集合,这些Java集合构成了Session缓存。只要Session实例没有结束生命周期,存放在它缓存中的对象也不会结束生命周期。故一级缓存也被称为是Session基本的缓存。
Hibernate的一级缓存有以下特色:
1. 当应用程序调用Session接口的save()、update()、saveOrUpdate()时,若是Session缓存中没有相应的对象,hibernate就会自动的把从数据库中查询到的相应对象信息加入到一级缓存中去。
2. 当调用Session接口的load()、get()方法,以及Query接口的list()、iterator()方法时,会判断缓存中是否存在该对象,有则返回,不会查询数据库,若是缓存中没有要查询对象,再去数据库中查询对应对象,并添加到一级缓存中。
3. 当调用Session的close()方法时,Session缓存会被清空。
证实一级缓存的存在:
1 @Test 2 public void demo8() { 3 Transaction tx = session.beginTransaction(); 4 Customer customer1 = session.get(Customer.class, 1l); // hibernate查询数据库 5 System.out.println(customer1); 6 Customer customer2 = session.get(Customer.class, 1l); // 不查询数据库 7 System.out.println(customer1==customer2); // true 8 System.out.println(customer2); 9 tx.commit(); 10 session.close(); 11 }
Hibernate向一级缓存放入数据时,同时复制一份数据放入到hibernate快照中,当使用commit()方法提交事务时,同时会清理Session的一级缓存,这时会使用oid判断一级缓存中的对象和快照中的对象是否一致,若是两个对象中的属性发生变化,则执行update语句,将缓存的内容同步到数据库,并更新快照:若是一致,则不执行update语句。Hibernate快照的做用就是确保一级缓存中的数据和数据库中的数据一致。