持久化:
所谓的持久化,就是将内存中的数据永久存储到关系型数据库中。
持久化类:
指一个java类与数据库表建立了映射关系,那么这个类称为持久化类。
持久化类的编写规则:
*持久化类需要提供无参数的构造函数。因为在Hibernate的底层需要使用反射生成类的实例。
*持久化类的属性需要私有,对私有的属性提供公有的get和set方法。因为在Hibernate的底层会将查询到的数据进行封装。
*持久化类的属性要尽量使用包装类的类型。因为包装类和基本数据类型的默认值不同,包装类的类型语义描述更清晰而基本数据类型不容易描述。
*持久化类要有一个唯一标识OID与表的主键对应。在Java中通过地址区分是否是同一个对象,在关系型数据库的表中是通过主键区分是否是同一条记录,而Hibernate需要通过这个唯一标识OID区分在内存中是否是同一个持久化类。Hibernate是不允许在内存中出现两个OID相同的持久化对象的。
*持久化类尽量不要使用final进行修饰。因为Hibernate中有延迟加载的机制,这个机制中会产生代理对象,Hibernate产生代理对象使用的是字节码的增强技术完成的,其实就是产生了当前类的一个子类对象实现的。如果使用了final修饰持久化类,就不能产生子类,从而就不能产生代理对象,那么Hibernate的延迟加载策略(是一种优化手段)就会失效。
主键的类型:
*自然主键:主键的本身就是表中的一个字段(实体中的一个具体属性),具有业务含义,称为自然主键。例如客户表中,如果把name字段作为主键,其前提条件是:每一个客户的姓名不允许为null,不允许客户重名,并且不允许修改客户姓名。不能满足不断变化的业务需求,一旦出现了客户重名的业务需求,就必须修改数据类型,重新定义表的主键,给数据库的维护增加了难度。
*代理主键:主键的本身不是表中必须的一个字段(不是实体中某个具体属性),不具有业务含义,称为代理主键。一般取名为ID,通常为整数类型。
实际开发中,尽量使用代理主键。
主键生成策略:
【increment】:Hibernate提供的自动增长机制,适用short、long、int类型的主键。在单线程中使用。
首先发送一条语句:select max(id) from 表,然后id+1作为下一条记录的主键。
【identity】:适用short、long、int类型的主键,采用的是数据库底层的自动增长机制,条件是数据库支持自动增长数据类型(mysql、DB2)。Oracle没有自动增长。
【sequence】:适用short、long、int类型的主键,根据底层数据库序列生成标识符。Oracle支持序列。mysql就不能使用序列。
【native】:本地策略,可以在identity和sequence之间进行自动切换。
【uuid】:适用于字符串类型的主键,采用128位的UUID算法生成标识符。
【assigned】:Hibernate放弃外键的管理,需要通过手动编写程序或用户自己设置。
主键生成策略在映射配置文件中设置:

持久化类的三种状态:
在Hibernate中持久化的对象可以划分为三种状态:瞬时态、持久态、托管态
【瞬时态(transient)】:没有唯一的标识OID、没有被session管理。
【持久态(persistent)】:存在唯一的标识OID、被session管理。持久化类的持久态对象可以自动更新数据库。
【托管态(detached)】:存在唯一的标识OID、没有被session管理。
public class HibernateDemo1 {
@Test
public void demo1() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();//瞬时态对象:没有唯一标识OID,没有被session管理
customer.setCust_name("赵武");
session.save(customer);//持久态对象:有唯一标识OID,被session管理
transaction.commit();
session.close();
System.out.println(customer);//托管态对象:有唯一标识OID,没有被session管理
}
}
Hibernate持久化对象的三种状态转换:

1、瞬时态:
【获得】:Customer customer = new Customer();
【瞬时态---->持久态】:save()、saveOrUpdate()执行save方法
【瞬时态---->托管态】:为瞬时态对象设置持久化标识。customer.setCust_id(1l);
2、持久态
【获得】:get()、load()、find()、iterate()
【持久态---->瞬时态】:delete()
【持久态---->托管态】:close()、clear()清除一级缓存的所有对象、evict(Object obj)清除一级缓存中的某一个对象。
3、脱管态
【获得】:Customer customer = new Customer(); customer.setCust_id(1l);
【脱管态---->瞬时态】:customer.setCust_id(null);
【脱管态---->持久态】:update()、saveOrUpdate()执行update方法
持久态对象特性:
持久态对象能够自动更新数据库
public class HibernateDemo1 {
@Test
public void demo1() {
Session session = HibernateUtils.getSession();
Transaction transaction = session.beginTransaction();
//获得持久态对象
Customer customer = session.get(Customer.class,1l);
customer.setCust_name("赵武");
//session.update(customer);//不用手动调用update方法就可以更新
transaction.commit();
session.close();
}
}
save()方法
- save()方法使一个瞬时态对象转变为持久态对象
- session的save()方法完成以下操作:
- 把News对象加入到session缓存中,使它进入持久化状态
- 选用映射文件指定的标识符生成器,为持久化对象分配唯一的OID。在使用代理主键的情况下,setId()方法为News对象设置OID是无效的。
- 计划执行一条insert语句:在flush缓存的时候
- persist()和save()区别:
- 当对一个OID不为null的对象执行save()方法时,会把该对象以一个新的oid保存到数据库中;但执行persist()方法时会抛出一个异常。
update()方法
- update()方法使一个托管态对象变为持久态对象,并且计划执行一条update语句
- 若希望session仅当修改了News对象的属性时,才执行update()语句,可以把映射文件中<class>元素的select-before-update设为true。该属性的默认值为false
- 当update()方法关联一个脱管态对象时,如果在session的缓存中已经存在相同的OID的持久态对象时,会抛出异常
- 当update()方法关联一个脱管态对象时,如果数据库中不存在相应的记录,也会抛出异常。
saveOrUpdate()方法
- saveOrUpdate()方法同时包含了save()与update()方法的功能
- 判定对象为临时对象的标准
- java对象的OID为null
- 映射文件中为<id>设置了unsaved-value属性,并且java对象的OID取值与这个unsaved-value属性值匹配。
delete()方法
- delete()方法即可以删除一个脱管态对象,也可以删除一个持久态对象
- delete()方法处理过程:
- 计划执行一条delete语句
- 把对象从session缓存中删除,该对象进入删除状态
- Hibernate的cfg.xml配置文件中有一个hibernate.use_identifier_rollback属性,其默认值为false,若把它设置为true,将改变delete()方法的运行行为:delete()方法会把持久态对象或脱管态对象的OID设置为null,使它们变成瞬时态对象。
418

被折叠的 条评论
为什么被折叠?



