Hibernate思维导图
Hibernate映射
关于hibernate的映射要说明的一点就是关于ID的访问权限,peroperty以及field的区别;
表的主键在内存中对应一个OID对象描述标识符,需要在配置文件中指定对象标识符的生成方式
assinged是自然主键的方式,这种策略需要用户指定ID才可以。
其他的方式比如sequence通过序列生成主键,identity,increment等是自增长,这种方式生成的主键一般是hibernate生成的,所以我们在编写实体对象的时候,id的get和set权限应该注意
class xxx{ private long id; public long getId(); private void serId(); }
在这里应该设置get的访问权限是public,set权限private,由于hibernate在访问实体模型的时候,是不考虑权限的,因此这样就避免了用户指定主键。
另外一个知识点就是,如果不通过property指定一个列,而使用field。那么hibernate就会直接访问属性,而不会通过get set访问属性
对象的映射标识符OID
这是一块相对来说也是hibernate重点,什么是OID?如何指定OID?OID与主键是什么关系?
什么是OID?
OID全拼是object identifier,也就是对象标识符,因为数据库表中一般都通过主键来识别一个中的不同行,而JVM中一般使用地址来识别不同的对象,在session缓存中,当然也需要一个标识符来表示不同的缓存对象,因此,OID也就排上了用场。
缓存的概念:
SessionFactory是重量级的缓存,里面包含了数据的连接,预定义的Sql等,而Session是轻量级的里面包含了一些增删查改的对象。
如果在一个JVM对象中,加入到不同的session中,也是不同的缓存对象,而不同的对象加入到同一个session中,也需要保证OID的不同,因为session不管你存的是什么都需要通过标识符来检索对象。
如何指定OID?
通常分为两种:
1.自然主键,也就是带有业务含义的,比如学生的学号,工作的编号,通常包含了年份,部门或者班级,专业等等业务上的意义,因此需要手动的合并或者拼接指定,这种情况下就需要使用assinged方式,这种方式如果不指定主键就提交缓存进行更新,会报错。
2 代理主键 也就是没有业务意义,通常通过编码自动生成
increment:不依赖于底层数据库,适合单个数据库场合不适合集群,必须为long int short类型。插入式,先选择最大的id值,再加1
identity:依赖底层数据库系统。支持自动增长字段: OID 为long,int,short
sequence:MYSQL不支持序列。依赖底层,必须支持序列。Oracle db2 sap db postgresql
hilo:计算公式hi*(max_lo+1)+lo 不依赖底层数据库系统,Long,int,short,只能在一个数据库中保持唯一
native:跨平台,自动选择使用哪个策略。
由于上面的identity,sequence都需要依赖于底层数据库,不同的数据库可能不支持这种方式。那么一般推荐使用native,自动进行选择。
OID与主键是什么关系
一般来说,OID就是一个对象持久化之前是null,持久化的时候hibernate或者我们手动指定一个id,这个ID被插入到数据库当做主键,在session中当做索引。也因为这个原因,需要保证OID与主键的一致性,比如类型啊,长度之类的。
关于Session缓存----清理缓存
缓存的概念,为了缓冲数据,减少与真实数据之间的交互,与计算机的缓存类似,经常访问硬盘的效率太低,IO太慢,就把内存当作缓存,CPU每次与内存直接交互,内存中找不到数据再去硬盘中读取。然而内存又觉得慢了,就弄个cahce当作缓存,经常访问的数据再放到这里,更加快了速度。
session缓存也是如此,与Web中的Session类似,在网页中,也有Session这样一种概念,比如我们登陆淘宝,会记录我们的用户信息,当浏览器关闭或退出时,Session关闭,这期间通过session来识别的用户的身份,无需每次登陆进行校验,hibernate也是如此,我们从SessionFactory中开启这个Session,持久化一个对象,然后提交事务,增删改查,最后关闭Session。
那么session缓存具体有什么作用:
比如我们通过Session.get(xxx.class,new Long(1));来获取Session中的OID为1的对象,它会首先到缓存中查找,如果找到了就直接用, 如果找逼到就去读取数据库,然后存储到缓存中,第二次就可以直接从获取数据了。
这样就减少了访问数据库的频率!
另外我们频繁的修改一个对象,如果这个对象放在缓存中,而且还是用了事务,那么只有在事务commit的时候,才会执行真正的sql语句!