标签:加载 sed 编码 也会 play 保存 int 讲解 hid
1.持久化类编写规则
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的主键生成策略。
2. Hibernate主键生成策略
主键的类型:在讲解Hibernate的主键生成策略之前,先来了解两个概念,即自然主键和代理主键,具体如下:
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快照的作用就是确保一级缓存中的数据和数据库中的数据一致。
标签:加载 sed 编码 也会 play 保存 int 讲解 hid
原文地址:https://www.cnblogs.com/eaglesour/p/9484523.html