Hibernate持久化类的编写规则
1.什么是持久化类
Hibernate是持久化层的ORM映射框架,所谓持久化,就是将内存中的数据永久存储到关系型数据库中。持久化类就是指一个Java类与数据库表建立了映射关系,那么这个类称为是持久化类。也可以说是Java类有了一个映射文件与数据库的表建立了关系。
2.持久化类的编写规则
1.持久化类需要提供无参数的构造方法。因为在Hibernate的底层需要使用反射生成类的实例。
2.持久化类的属性需要私有,对私有的属性提供共有的get和set方法。因为在Hibernate底层会将查询到的数据进型封装。
3.持久化类的属性要尽量使用包装类的类型,因为包装类和基本数据类型的默认值不同,包装类的类型语义描述更清晰而基本数据类型不容易描述。
4.持久化类要有一个唯一标识OID与表的主键对应。因为Hibernate中需要通过这个唯一标识OID区分在内存中是否是同一个持久化类,在Java中通过地址区分是否是同一个对象的,在关系型数据库的表中是通过主键区分是否同一条记录。那么Hibernate就是通过这个OID来进行区分的。Hibernate是不允许在内存中出现两个OID相同的持久化对象的。
5.持久化类尽量不要使用final进行修饰。因为Hibernate中有延迟加载的机制,这个机制中会产生代理对象,Hibernate产生代理对象使用的是字节码的增强技术完成的,其实就是产生了当前类的一个子类对象实现的。如果使用了final修饰持久化类。那么就不能产生子类,从而就不会产生代理对象,那么Hibernate的延迟加载策略(是一种优化手段)就会失效。
3.Hibernate主键生成策略
1.主键的类型
自然主键:把具有含义的字段作为主键,称之为自然主键。
代理主键:把不具备业务含义的字段作为主键,称之为代理主键。该字段一般取名为“ID”,同城为整数类型,因为整数类型比字符串类型要节省更多的数据库空间。
2.Hibernate的主键生成策略
increment:用于long、short或int类型,由Hibernate自动以递增的方式生成唯一标识符,每次增量为1。只有当没有其他进程向同一张表中插入数据时才可以使用,不能再集群环境下使用。适用于代理主键。
identity:采用底层数据库本身提供的主键生成标识符,条件是数据库支持曾东增长数据类型。在DB2、MySQL、MS SQL Server、Sybase和HypersonicSQL数据库中可以使用该生成器,该生成器要求在数据库中吧主键定义为自增长类型。适用于代理主键。
sequence:Hibernate根据底层数据库序列生成标识符。条件是数据库支持序列。适用于代理主键。
native:根据底层数据库对自动生成标识符的能力来选择identity、sequence、hilo三种生成器中的一种。适合跨数据库平台开发。适用于代理主键。
uuid:Hibernate采用128位的UUID算法来生成标识符。该算法能够在网络环境中生成唯一的字符串标识符,其UUID被编码为一个长度为32位的十六进制字符串。这种策略不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。只用于代理主键。
assigned:由java程序负责生成标识符,如果不能指定id元素的generator属性,则默认使用该主键生成策略,适用于自然主键。
4.Hibernate的持久化对象的三种状态
持久化对象三种状态的概述
1.瞬时状态(transient)
瞬时态也城外临时态或者自由态,瞬时态的实例是由new命令创建、开辟内存空间的对象,不存在持久化表示OID(相当于主键值),尚未与Hibernate Session关联,在数据库中也没有记录,失去引用后将被JVM回收。瞬时状态的对象在内存中是独立存在的,与数据库中的数据无任何关联,仅是一个信息携带的载体。
2.持久态(persistent)
持久态的对象存在持久化标识OID,加入到了Session缓存中,并且相关联的Session没有关闭,在数据库中有对应的记录,每条记录只对应唯一的持久化对象,需要注意的是,持久态对象是在事务还未提交前变成持久态的。
3.脱管态(detached)
脱管态也称离线态或者游离态,当某个持久化状态的实例与Session的关联被关闭时就变成了脱管态,脱管态对象存在持久化标识OID,并且仍然与数据库中的数据存在关联,只是失去了与当前Session的关联,脱管状态对象发生改变时Hibernate不能检测到。
三种状态转换
持久态对象能够自动更新数据库
5.Hibernate的一级缓存
缓存是计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存。
Hibernate的缓存分为一级缓存和二级缓存,Hibernate的这两级缓存都位于持久化层,存储的都是数据库数据的备份。其中第一级缓存为Hibernate的内置缓存,不能被卸载。
1.什么是Hibernate的一级缓存
Hibernate的一级缓存就是指Session缓存,Session缓存是一块内存空间,用来存放相互管理的java对象,在使用Hibernate查询对象的时候,首先会使用对象属性的OID值在Hibernate的一级缓存中进行查找,如果找到匹配OID值的对象,就直接将该对象从一级缓存中取出使用,如果没有找到相同OID值的对象,则会去数据库中查找相应数据。当从数据库中查询到所需数据时,该数据信息也会放置到一级缓存中。Hibernate的一级缓存的作用就是减少对数据库的访问次数。
2.一级缓存的内部结构:(快照区)
Hibernate想一级缓存放入数据时,同时复制一份数据放入到Hibernate快照中,当使用commit()方法提交事务时,同时会清理Session的一级缓存,这时会使用OID判断一级缓存中的对象和快照中的对象是否一致,如果两个对象中的属性发生变化,则执行update语句,将缓存的内容同步到数据库,并更新快照;如果一致,则不执行update语句 Hibernate快照的作用就是确保一级缓存中的数据和数据库中的数据库一致。
6.Hibernate的事务控制
1.什么是事务
事务(Transaction)是由一条或多条操作数据库的SQL语句组成的一个不可分割的工作单元,当事务中的所有操作都正常完成时,整个事务才能被提交到数据库中,如果有一项操作没有完成,则整个事务会被回滚。
2.事务的四个特征
原子性,一致性,隔离性,持久性通常称为ACID特性。
3.事务的并发问题
脏读:一个事务读取到另一个事务未提交的数据。
不可重复读:一个事务督导了另一个事务已经提交的update的数据,导致在同一个事务中的多次查询结果不一致。
虚度/幻读:一个事务读到了另一个事务已经提交的insert的数据,导致在同一个事务中的多次查询结果不一致。
4.事务的隔离级别
读未提交(Read Uncommitted,一级):可防止丢失更新
已提交读(Read Committed,二级):防止脏读
可重复读(Repeatable,四级):防止不可重复读和脏读
序列化/串行化(Serializable,八级):防止脏读,不可重复读和幻读。
5.Hibernate中的事务管理
在Hibernate中,可以通过代码来操作管理事务,如下
Transaction tx = session.beginTransaction();
开启一个事务;持久化操作后,通过“tx.commit();”提交事务,如果事务出现异常,有通过tx.rollback();操作来撤销事务(事务回滚)。
在Hibernate配置文件中对事务进行配置。配置文件中,可以设置事务的隔离级别。其具体方法是在hibernate.cfg.xml文件中的
标签元素中进行的。
在Hibernate的配置文件中,hibernate.current_session_context_class 属性用于指定Session管理方式,可选值包括
thread:Session对象的生命周期与本地线程绑定
jta:Session对象的生命周期与JTA事务绑定
managed:Hibernate委托程序来管理Session对象的生命周期
在hibernate.cfg.xml中进行如下配置
<property name="hibernate.current_session_context_class">thread</property>
hibernate提供sessionFactory。getCurrentSession()创建一个session和ThreadLocal绑定方法。
而且Hibernate中提供的这个与线程绑定的session可以不用关闭,当线程执行结束后,就会自动关闭。
7.Hibernate中的批量查询
1.HQL查询
HQL – hibernate Query Language(多表查询,复杂时不好使用)
上诉语句就是先书写HQL语句,可以省略select
然后根据HQL语句创建查询对象
然后根据查询对象获得结果
最后打印查询出来的结果
下面的是?号占位符 加了一条设置参数的语句
后面获得结果用的是uniqueResult()方法是因为查出来的是单一结果所以可以使用。
还可以用这种方式来设置参数
以分页查询
2.Criteria查询(单表条件查询)
Hibernate自创的无语局面向对象查询
基本查询
条件查询
分页查询和HQL一样
查询总记录数
3.原生SQL
1.基本查询
返回的是Object数组
封装到对象中使用query.addEntity();方法
条件查询用setParameter();来设置参数
分页查询用limit然后设置参数即可