在持久化层,对象分为哪些状态?
- 瞬时态(transistant):对象创建时,瞬时对象在内存孤立存在,携带信息的载体,不和数据库有任何关联,在hibernate里面,可以使用session的save()或saveOrUpdate()将瞬时态转为持久态
- 持久态(Persistent):该对象在数据库已有对应的记录,并且拥有一个持久化标识,如果是使用hibernate的delete()方法,对应的持久态会变成瞬时态,因为此时他不和数据库有任何关联;当session执行close()或者clear()、evict(),持久态变成托管态,因为此时该对象已经不再hibernate持久层的管理之下
- 与session实例关联
- 在数据库有关联记录
- 托管态(Detached):当session执行close()或者clear()、evict(),持久态变成托管态,因为此时该对象已经不再hibernate持久层的管理之下;可以通过update()、saveOrUpdate()等方法,转变成持久化对象
- 本质上和瞬时对象相同,没有任何变量引用它时,JVM会在适当的时候进行回收
- 比瞬时对象多了个数据库标识值
hibernate和JDBC
- hibernate是基于JDBC的,它对JDBC访问数据库做了封装,大大的简化了数据访问层繁琐的重复性代码
- 性能比较好,属于轻量级的框架,支持多种关系数据库,和多种映射关系
开发流程
- 配置Configuration
- 创建sessionFactory
- 开启session
- 开始事务
- 操作数据库
- 提交事务
- 关闭session
- 关闭sessionFactory
延迟加载
延迟加载是为了避免一些无谓的性能开销提出来的,所谓的延迟加载就是当真正需要数据的时候才执行数据加载的操作,在hibernate中提供了对实体对象和集合的延迟加载。
hibernate查询方式
HQL,SQL,Criteria
HIbernate如何处理事务
hibernate是对JDBC的轻量级对象封装,本身不具备transaction处理功能,hibernate的transaction是底层JDBC的封装或者是JTA transaction的封装,取决于hibernate.properties中的配置;默认是JDBC的transaction
hibernate的缓存机制
hibernate的一级缓存:session级别的缓存,在session接口的实现中包含一系列的java集合,这些java集合构成了session缓存;持久化对象也保存在一级缓存
- 当使用session的save()时,持久化一个瞬时态对象,该对象被载入内存,即使以后不使用这个对象,缓存不清空时,该对象仍然处于生命周期;当使用load()和get()时,会先在缓存中查找,有则返回,无者加载。
- session能够在某些时间点,按照缓存中的变化执行相应的sql语句,来同步数据库,这一过程称作flush
- hibernate向session缓存放入数据时,会同时保存快照数据(数据库备份),当修改一级缓存,进行flush时,会对比缓存和快照,如果不一致,就会使用update更新
一级缓存的操作:flush,clear,evict,reflush
flush
:将缓存变化同步到数据库
clear
:将缓存清空
evict
:清除一级缓存指定的对象
refresh
:重新查询数据库,更新快照和一级缓存
hibernate的二级缓存:sessionFactory级别的缓存,属于进程范围的缓存,分为两个部分:内置和外置
- 内置:hibernate自带的,不可卸载,通常在hibernate初始化阶段,hibernate会把元数据和预定义的sql语句放到sessionFactory的缓存,内置缓存属于只读的
- 外置:可配置的缓存插件,外置缓存中的数据是数据库数据的复制,,必须引入第三方插件才能使用
二级缓存的并发策略
- transactionnal: 提供repeatable read事务隔离级别,缓存事务支持,发生异常的时候能够回滚
- read-write:提供read commit事务隔离级别,更新缓存时会锁定缓存中的数据
- non-read-write:会导致脏读
- read-only:数据只读,不允许修改
二级缓存常用技术
- EHCache
- OSCache
- SwarmCache
- JBOSSCache
hibernate的三种检索策略
- 立即检索:立即将查询对象查询出来加进缓存,并且将其关联对象也加载出来,这样做能够及时加载自身数据和关联对象数据,但是比较占内存和执行过多的select语句。
- 对应用程序完全透明,不管处于持久态还是游离态,应用程序都可以方便的从一个对象导航到与他关联的对象
- select语句太多,可能应用程序加载到不需要的对象而浪费内存
- 立即检索lazy=true
- 延时检索:在不涉及到连级操作单张表时,只适用 session 的 load 方法,只有在用到对象除 id 以外的属性时才会去加载对象;在涉及到关联类操作时,只有在用到关联对象的时候才会去加载
- 由程序决定加载哪些内容,避免了大量无用的查询语句
- 在session关闭后,就不能访问关联类的对象了,强行访问会发生懒加载异常
- 左外连接检索:采用左外连接检索,能够使用SQL的外连接查询将关联对象加进缓存中
- 使用了外连接,select语句数目少
- 可能会加载应用程序不需要的对象进缓存,白白浪费内存,同时复杂的数据库表连接也会影响检索性能。
hibernate的inverse作用
inverse属性默认是false,就是说关系的两端都来维护关系。
- 比如student和teacher表,是多对多的关系,用一个TeacherStudent维护
- 如果student这边inverse= true,说明TeacherStudent维护由teacher表负责,当操作student表不会操作TeacherStudent;当teacher表操作时,会触发对TeacherStudent的操作;所以两边inverse都为true是错误的设置
JDBC/Hibernate/ibatis的区别
JDBC
- 手写sql
- delete,insert,update要一个个 将对象的值取出来放到sql语句中,不能直接传一个对象
- select返回一个resultSet,需要从resultSet一行行遍历,然后遍历每一行的字段,取值封装成对象
HIbernate
- 不写sql
- delete,insert,update可以直接取对象
- select直接返回对象
Ibatis
- 手写sql
- delete,insert,update可以直接取对象
- select直接返回对象