介绍
Hibernate是一个ORM(Object-Relational-Mapping,对象关系映射)框架,它提供了另一种管理数据库的思想,即将表与对象进行对应,数据库中的每一张表都与一个对象对应,在Hibernate中对于数据的操作都要在session中进行,session的本质是一个连接(Connection),使用session保存对象时,即向数据库中的一张表中插入数据.那么对于session的操作目标,对象有什么特殊要求呢?
对象(数据类)
1/需要提供无参构造(底层使用反射创建实例);
2/所有字段应尽量为引用类型
因为基本类型无法用于表达无这个概念,比如int作为字段时会有默认值0,而0是有意义的,所以应使用Integer,默认值为NULL
3/为所以字段提供get/set方法
4/不能使用final修饰
这里涉及到session的get()/load()方法的区别,get()方法是直接返回的一个数据类对象,而load()返回的是一个CGlig代理对象,而CGlib是返回的一个子类对象,所以使用final修饰后便不能再生成子类对象.还有一点区别时,使用load()时还使用了延时加载技术,即当调用load方法时,并没有立即发送SQL语句,仅当操作代理对象时,才会发送SQL语句,查询相关数据.
5/必须为对象提供id属性
开发中建议使用代理主键,不建议使用自然主键.在笔者的文章Hibernate框架的一级缓存与快照技术中向读者介绍了Hibernate的一级缓存与快照技术,当session管理一级缓存时以什么依据来区分每个对象呢?!没有错,就是使用的id,所以id的重要性不言而喻.
数据类对象的三种状态
瞬时态-TO(Transient Object):无id,不在session中.数据库中没有
技术态-PO(Persistence Object):有id,在session中.数据库中也不一定有,开启事务的情况下,进行了回滚操作.
托管态或游离态-DO(Detach Object):有id,不在session中.数据库中也不一定有,id可以手动设置.
在对数据进行修改时,建议不要对DO进行操作,因为有可能会引发异常,比如DO与一级缓存中的PO具有相同的id,或者StaleStateException,导致的原因是使用Hibernate执行删除和使用SQL执行删除的状态不一致导致的.建议使用PO进行操作,因为Hibernate是可以检测到一级缓存中的数据是否发生修改的(快照技术),发生修改后会自动对数据库中的数据进行更新.