Hibernate持久化状态&主键生成策略
持久化类
持久化:将内存中的一个对象持久化到数据库中的过程
持久化类:Java类+映射文件。Java中一个类与数据库的表建立了映射关系,那么这个类称为持久化类。
持久化类的编写规则:
- 对持久化类提供一个无参构造,Hibernate底层需要通过反射生成实例。
- 对属性需要私有,对私有属性提供公有的set、get方法,Hibernate中获取、设置对象的值。
- 对持久化类提供一个唯一标识OID与数据库主键对应,Java中通过对象的地址区分是否是同一个对象,数据库中通过主键确定是否是同一个记录。HIbernate通过持久化的oid属性区分是否同一个对象
- 持久化类的属性尽量使用包装类的类型,而不是基本数据类型,因为基本数据类型默认值是0,会有很多歧义,而包装类的默认值是null。
- 持久化类不要用final进行修饰 ,延迟加载本身是Hibernate的一个优化的手段,返回的是一个代理对象(javasist可以对没有实现接口的类产生代理,使用了非常底层的字节码增强技术,继承这个类进行代理)如果不能被继承,延迟加载失效,load和get一致。
持久化类的三种状态(了解):
瞬时态:这种没有唯一标识oid,没有被session管理
持久态:有唯一标识oid,被session管理,持久化类的持久态的对象,可以自动更新数据库(一级缓存,后面介绍)。
脱管态:有唯一标识,没有被session管理
区分三种状态对象:
持久化类的状态转换:(了解)
瞬时态对象:
获得: Customer c = new Customer();
状态转换:瞬时转持久: session.save() , session.saveOrUpdate()
瞬时转脱管: Customer.setCust_id(1); 瞬时与脱管的区别在于有没有oid
持久态对象:
获得:session.get , session.load : Customer customer = session.get(Customer.Class , 1 ); 被session管理,有oid
状态转换:转瞬时:session.delete();
转脱管:session.close();
脱管态对象:
获得:new 一个对象,为其设置id
状态转换:转持久:update \ saveOrUpdate,有id,被session管理
转瞬时:customer.setCust_id(null);
主键生成策略:
主键的分类:
自然主键:主键的本身是表中的一个字段(实体中一个具体的属性),比如身份证号。
代理主键:用一个与这个表不相关的字段id(PNO),这种主键称为代理主键。
实际开发当中尽量使用代理主键,一旦自然主键参与业务逻辑,后期可能需要修改源代码。好的程序的设计满足OCP原则。对程序的扩展是open的,对修改源码是close的。
Hibernate的主键生成策略:
实际开发中一般不允许用户手动设置主键,一般将主键讲给数据库,手动编写程序进行设置。在Hibernate中为了减少程序的编写,提供了很多主键的生成策略。
- increment:Hibernate中提供的自动增长机制,适用于int、short、long。仅在单线程中使用。首先发送查询语句,然后让id+1,作为下一条记录的主键。
- indentity:适用于short、int、long类型的主键,使用数据库底层的自动增长机制,适用于有自动增强机制数据库(MySQL),但是Oracle没有自动增长机制。
- sequence:适用于short、int、long类型的主键,采用序列的方式,(Oracle支持序列,MySQL不行)
- UUID:适用于字符串类型的主键,使用Hibernate中一种随机的方式生成字符串主键
- native:本地策略,可以在indentity和sequence之间进行自动切换,注意只能是short,int , long类型的主键,不适用String类型的主键。
- assigned:Hibernate放弃外键管理,需要通过手动编写程序或者用户自己设置。
- Foreign:外部的,一对一的一种关联映射的情况下使用(了解)。