首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

视传智播客_hibernate 领悟与总结(三)

2012-06-22 
看传智播客_hibernate 领悟与总结(三)继承映射:单张表采用:subclass nameSub discriminator-value1

看传智播客_hibernate 领悟与总结(三)
继承映射:
单张表采用:<subclass name="Sub" discriminator-value="1"/>和discriminator鉴别器,例如:<discriminator column="type" type="int"/>
鉴别器默认值是字符串。
多张表采用:<joined-subclass/>例:
<joined-subclass name="Skiller" table="引用的表">
<key column="外键名,可以随便取,它会自动引用"/>
<property name="属性名"/>
</joined-subclass>
折中:
<subclass name="引用表名" discriminator-value="2">
<join>
<key column="emp_id"/>
<property name="sell"/>
</join>
</subclass>
每个具体类单独一张表(每个表的ID不允许重复,所以不能采用native(identity)创建主键生成策略)可采用高低位主键生成策略(hilo),并且鉴别器也不需要了,因为都放到单独的每张表里去了,在查询上效率不是很高:
<union-subclass>
<property name="sell"/>
</union-subclass>
温馨提示:表的数目不要高于类的数目,对于性能上比较好。

懒加载(提高性能,避免一些不必要的数据库查询):
通过asm和cglib二个包实现。(可以动态的修改装入内存的字节码,可以动态生成字节码文件。)
在缺省的情况下Hibernate会对所有的对象进行懒加载,包括集合。
domain对象不可以是final的。
1.session.load懒加载。(使用load的时候不能判断对象是不是为空的。)可用Hibernate.initialize(对象);进行初始化。要在session未关闭时进行初始化。(load很少使用,一般是在你想建立两个对象之间的关联,而你又不想去访问数据库的时候。但是这样的应用场景是比较小的。故而load也用的比较小。)
2.one-to-one(元素)懒加载(起到的效果不是很好,一对一:Hibernate对于主对象一般不采用懒加载,是采用连接来查询的):
(lazy什么时候抓取数据,缺省为proxy代理,fetch采用什么方式抓取数据,缺省select,当fetch="join"的时候会影响lazy懒加载,可以采用缺省值,不配置)
必需同时满足下面三个条件时才能实现懒加载
(主表不能有constrained=true,所以主表没有懒加载)
lazy!=false 2)constrained=true 3)fetch=select
3.one-to-many (元素)懒加载:1)lazy!=false 2)fetch=select
4.many-to-one (元素):1)lazy!=false 2)fetch=select
5.many-to-many (元素):1)lazy!=false 2)fetch=select
6.能够懒加载的对象都是被改写过的代理对象,当相关联的session没有关闭时,访问这些懒加载对象(代理对象)的属性(getId和getClass除外)hibernate会初始化这些代理,或用Hibernate.initialize(proxy)来初始化代理对象;当相关联的session关闭后,再访问懒加载的对象将出现异常。


懒加载的一种解决方案:传递boolean值,如果需要则初始化Hibernate.initialize(对象);
例如:
if(boolean){Hibernate.initialize(对象);}

从缓存拿数据的方法不多只有三种分别为:get(),load()方法,iterator(),Query和crite都不行。
清空缓存的方法 :evict()清空一条数据。clear()清空所有缓存,一级缓存限制比较多,范围比较小,是完全缓存到内存中的,数据一天,就可能造成内存溢出,

二级缓存:
打开设置:1.这个可配,可不配,默认是打开的。<property name="cache.use_second_level_cache">true<property/>
 2。指定缓存的实现者,即由谁来提供缓存。<property name="cache.provider_class">org.hibernate.cache.OSCacheProvider</property>
有些缓存提供进需要进行相应的配置。
 3.指定需要缓存的类。在配置中可用如:<class-cache class="cn.itcast.hibernate.domain.User" usage="read-only">
或者在实体映射中配置:<cache usage="read-wirte">

打开统计信息:<property name="generate_statistics">true</property>.默认是关闭的,因为打开统计信息,消耗的资源会比较的多。
使用统计信息:
Statistics st = HibernateUtil.getSessionFactory().getStatistics();//获得统计信息
System.out.println(st);//输出统计信息
统计信息输出分析:
例如:Statistics [start time="12312312312"]//开始时间
sessions opend=3,session closed=3,如果两个值不一致,有可能造成连接泄漏。
tansactions=1;//成功的事务
successful transaction=1;
optimistic lock failuree=0;//乐观锁
flushes=1;//刷新过一次
connections obtained=2;//获得过两次连接
statements prepared=2;
statements closed=2;//statements对象产生了两次,关闭了两次。
second level cache puts=1;//二级缓存放入的次数。
second level cache hit=1;//命中了的次数。
second level cache misses=1;//有多少次没找到。
后面的是实体的信息。
例如:
System.out.println("put:"+st.getSecondLevelCachePutCount());//暴露了
System.out.println("hit:"+st.getSecondLevelCacheHitCount());//命中了
System.out.println("miss:"+st.getSecondLevelCacheMissCount());//错过了


查询的命中率是很底的。如果想利用query也进行缓存的话:可以把这个缓存打开:<property name"cache.use_query_cache"/>true</property>,而且还要设置缓存。如query.setCacheable(true);如果查询的缓存打开需要注意一下缓存的时间。


使用缓存的条件
1.读取大于修改。
2.数据量不能超过内存容量。
3.对数据要有独享的控制。
4.可以容忍出现无效数据。

分布式事务:
JTATransaction
可以简单的理解成跨数据库的事务,由应用JTA 容器实现;使用JTATransaction需要配置hibernate.transaction.factory_class参数,该参数缺省值是org.hibernate.transaction. JDBCTransactionFactory,当使用JTATransaction时需要将该参数改成org.hibernate.transaction.JTATransactionFactory,并配置jta.UserTransaction参数JNDI名(Hibernate在启动JTATransaction时要用该值到JNDI的上下文Context中去找javax.transaction.UserTransaction)。
javax.transaction.UserTransactin tx = context.lookup(“jndiName”);
try{
tx.begin();
//多个数据库的session操作;//内部就不要再用事务了。
//session1….
//session2….
tx.commit();
}catch(Exception e){
tx.rollback(); throw e;
}


事务的边界:事务的开始,事务的提交,事务的回滚,它们是什么时候开始,什么时候结束,这叫做事务的边界。

添加乐观锁:即以版本号的形式进行事务的控制。在实体映射中<version name="实体属性名">.


离线查询:DetachedCriteria可在session外创建(在其他层创建比如在Service中创建)然后用getExecutableCriteria(session)方法创建Criteria对象来完成查询。
Example查询:Example.create(obj);criteria.add(example)。


事件监听:
1:实现监听器的接口;如:SaveOrUpdateEventListener
2.配置Hibernate文件:如:
<event type="save(监听的类型)">
<listener class="cn.hibernate.event.def.DefaultSaveOrUpdateEventListener(这是Hibernate的缺省的保存和更新的实现)"/>
<listener class="cn.itcast.hibernate.SaveListener(实现监听的类)"/>
</event>

使用SQL语句进行查询(不太建议使用SQL语句进行查询,会有兼容性的问题):
例如:
Query q = session.createSQLQuery("select * from user").addEntity(User.class);
List<User> rs = q.list();
for(User r:rs)
System.out.println(r.getName());
命令查询(注意:query可以写在映射文件的class中,但引用的时候就要写完整的路径名了,如果不写在class中就要保证起的名字是唯一):
1.在配置映射文件中编写HQL或SQL语句
例如:
<query name="getUserByBirthday">
<![CDATA[HQL语句 from User where birthday=:birthday]]>
</query>
2.使用:
Query q= s.getNamedQuery("getUserByBirthday");
q.setDate("birthday",new Date());

热点排行