hibernate学习2

来源:互联网 发布:ios手游能在mac上玩吗 编辑:程序博客网 时间:2024/04/29 18:05

hibernate学习2

数据访问 po(persistence object) 和 vo(value object)
vo就是简单的值对象
po是值
1.纳入hibernate管理框架中(entity map)的vo ,po的变化会在事务提交时将反应到实际数据库中
2.hibernate返回的对象也是po
Hibernate_DEV_GUIDE.pdf
Hibernate_3.2.0_Reference_zh_CN.chm
session关闭 po就变成vo
从设计层面而言,应该避免直接po传递到系统中的其他层面,一种解决办法是vo作为DTO (data transfer object)
例子一:
userBean从数据库加载,同时userBean对象的相关对象address也被加载,此时向userBean增加一个address对象
session.save(user),hibernate 会更具unsaved-value判断哪些需要执行save操作。新增加滴地址id为null,unsaved-value(null)相同,为未保存对象将产生insert语句。“原有”关联对象id和数据库里面一样,unsaved-value(null) 不一样,就不进行保存
inverse和cascade
inverse=“false” 为主动方,由主动方负责维护关联关系(一对多)
casecade级联 对user进行save的时候 同时对address也执行save
延时加载
避免关联关系带来无味的性能开销
session关闭后就获取不到 user关联对象的address的信息
那怎样才能在session关闭后还能继续加载user的关联对象address的信息呢?
强制加载关联对象实现 hibernate.initialize方法
hibernate为了实现延时加载,对jdk的collection接口进行了独立的实现。
所有编写pojo的时候必须用jdk的 collection接口 如:set,map 而不能用jdk collect实现 hashSet HashMap等
这样实现只有程序真正调用collection时,才激发底层实际的数据库操作
事务管理jta 事务 和jdbc事务
//jdbc事务
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//默认 AutoCommit=false
//如果 是下面语句 代码将不会对数据库产生任何效果
session.save(user);
session.close();
正确代码如下:
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
jta可以实现跨session的事务
jta可以跨越多个jdbc connection 生命周期
显示声明事务
UserTransaction tx = new InitialContext().lookup("....");

锁(悲观锁、乐观锁)
悲观锁(将数据锁定)对本系统其它事务和外部系统的事务处理持保守状态,依靠数据库提供的锁机制,保证数据的排他性,否则本系统加锁了,也不能保证外部系统不会修改数据
//一个典型的例子:
select * from t_user where name = "csy" for update
锁住了 t_user表中说有 符合条件(name="csy")的记录
 
String hqlStr = "from UserBean as user where user.name='csy'"
Query query = session.createQuery(hqlStr);
query.setLockMode("user,LockMode.UPGRADE");//加锁
List userList = query.list();
乐观锁
悲观锁大部分是依靠数据库的硕机制实现,以保证操作最大程度的独占性,这样会使数据库性能的大量开销,特别是对长事务而言,这样的开销往往无法承受
 
乐观锁机制 大多数是基于数据版本(version),即为数据增加一个版本标识,为数据库表增加一个“version”字段来实现
读取数据的时候将此版本号一同读出,之后更新时,对此版本号加一,判断过期条件是:提交的数据版本号大于数据库表当前版本号,者予以更新,否则认为是过期数据
乐观硕避免了长事务中的数据库加锁开销 大大提高了并发量
 
乐观硕的缺陷
外部系统对数据进行操作,不受我们系统的控制,因此可能会造成脏数据被更新到数据库中。 在系统设计阶段,进行调整(如将乐观锁策略在数据库存储过程中实现,对外开放的是存储过程而不是数据库表)
hibernate配置:
optimistic-lock="version"
hibernate 分页
数据分页显示,不同的数据库分页模式往往各不相同,带来了数据库可移植的问题
hibernate 通过不同数据库的统一接口设计
 
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("age","20"));
criteria.setFirstResult(100);
criteria.setFetchSize(20);
hibernate 通过不同的方言dialect来构造返回限定子句
如:mysql限定语句是limit 而oracle通过rownum句子来实现
cache管理
如果把数据在本地内存保存一个镜像就会提高很多的效率
使用缓存需要考虑数据的有效性
1.我们系统于第三方系统共享数据库的情况下,hibernate的cache机制可能失效(原因是 第三方系统对数据库进行了更改,和ibernate并不知道数据库中的数据已经发生了变化,也就是池中的数据还是修改之前的版本,hibernate会将此数据返回给上层代码,有潜在问题)
2.统一系统中 基于hibernate和基于jdbc的两中数据访问方式并存

 
java的cache实现 最简单的是hashTable 但是有性能实现
第三方cache实现
jcs EHCache OSCache \JBoss Cache \SwarmCache等
cache 分为两中
1.session级别的cache 属于事务级别的缓冲 一旦事务结束 cache也就失败,这为内置实现,无需我们进行干涉
2.第二层cache 是对其实例范围内的数据进行缓冲的管理,EHCache为默认的第二级cache实现
但EHCache 不支持分布式缓冲,如果我们的系统需要要在多台设备上部署,并共享同一个数据库必须使用分布式缓冲的Cache如SwarmCache/JBossCache

其中SwarmCache提供的是invalidation方式的分布式缓存,即当集群中的某一个节点更新了缓存中的数据,即通知集群中的其他节点将此数据废除,之后各个节点需要用到这个数据的时候,会重新从数据库中读入并填充到缓存中
JBossCache 提供的是Reapplication式的缓冲,即如果集群中某个节点的数据发生改变,此节点会将发生改变的数据的最新版本复制到集群中的每个节点中以保持所有节点状态一致
 
配置如下:
1.对ihibernate.cfg.xml配置
2.对EHCache进行配置
3.指定映射实体类的cache策略
<cache usage="read-write"/>
配置好后hibernate在运行期间会自动应用cache机制,也就是说。我们对po的更新,会自动同步到cache中
hibernate的查询机制
 
Query.list();//产生一条select sql 获取所有的记录
Query.iterate();//产生一条select sql 获取所有记录的id ,通过id查询所有的记录。n+1条语句
区别
list不会从cache中取数据
iterate会更具id从cache中取数据
海量数据的时候使用iterate提高性能
session的管理
session中包含数据库操作相关的状态信息,对session的管理类似于jdbc的 jdbc Connection 的调度管理
避免session的频繁的创建和销毁 ,从而避免大量的内存开销和频繁的jvm回收
session的管理方案中,threadLocal模式得到了大量的使用
sessionFactory是线程安全的。
session不是线程安全的
ThreadLocal 的独特之处就是会给每个线程维护一个私有的变量空间
实现原理是在jvm里面维护一个map,map的key是当前线程对象,value是通过ThreadLocal.set方法保存的对象实例
可以通过过滤器来实现对session的管理