`

hibernate总结

 
阅读更多

hibernate建立数据的的映射是完全可以通过eclips自动导入实现的,不过,基础还是要学的。知其解决方法,也要知其理才行~!

(~ o ~)~zZ  以下是收获:

---------------------------------------------------------------------------------------------

xml形式的实体化映射:

 

*.hbm.xml
<hibernate-mapping>
<class name="实体化类名" table="表名">
   <id> 定义一个单主键,一个字段  属性作为实体类的主键
   <composite-id> 复合主键,多个字段  一组属性作为主键的定义方式 (主键类,实现序列化接口)
   <property> 字段---》属性的映射
  </class>

</hibernate-mapping>

 

练习:
emp-->dept   多对一  实现级联,添加,删除操作

 

首先写好emp和dept实体化类   emp为主表实体化类,所以emp有dept类的对象作为属性

接着写映射文件.hbm.xml

emp.hbm.xml如下:

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!--   
  5.     Mapping file autogenerated by MyEclipse Persistence Tools  
  6. -->  
  7. <hibernate-mapping package="cn.com.vo">  
  8.     <class name="Emp" table="emp">  
  9.         <id name="empno" column="empno">  
  10.             <generator class="increment"></generator>  
  11.         </id>  
  12.         <property name="ENAME" column="ENAME"></property>  
  13.         <property name="JOB" column="JOB"></property>  
  14.   
  15.         <property name="MGR" column="MGR"></property>  
  16.         <property name="HIREDATE" column="HIREDATE"></property>  
  17.         <property name="SAL" column="SAL"></property>  
  18.         <property name="COMM" column="COMM"></property>  
  19.         <many-to-one name="dept" column="deptno" outer-join="true"  
  20.             cascade="all">  
  21.         </many-to-one>  
  22.   
  23.     </class>  
  24.   
  25. </hibernate-mapping>  

 

dept.hbm.xml 如下:

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!--   
  5.     Mapping file autogenerated by MyEclipse Persistence Tools  
  6. -->  
  7. <hibernate-mapping package="cn.com.vo">  
  8. <class name="Dept" table="dept">  
  9. <id name="DEPTNO" column="DEPTNO" >  
  10.   <generator class="increment"></generator>  
  11. </id>  
  12. <property name="DNAME" column="DNAME"></property>  
  13. <property name="LOC" column="LOC"></property>  
  14.   
  15. </class>  
  16.   
  17. </hibernate-mapping>  

 

 

 注意了:
在写pojo类时,*.hbm.xml写完之后,
还要将hibernate.cfg.xml之后加入
<mapping resource="cn/com/vo/Emp.hbm.xml" />
<mapping resource="cn/com/vo/Dept.hbm.xml" />类似这样的地址,实现pojo类在hibernate中的关系映射


(自动通过数据库导入的pojo类,eclips会自动将其地址加在hibernate.cfg.xml中

hbm2ddl.auto  这个在hibernate.cfg.xml中若是设置为true,则会根据映射关系在数据库中建立相应的table,假如数据有了~就不会建了。

 

cascade 有以下取值:

 

all : 所有操作都传递到相关联的对象
save-update 保存和更新传递到相关联的对象
delete 删除操作传递到相关联的对象
delete-orphan : 所有操作都传递到相关联的对象 并删除不再与父对象关联的对象。

-----------------------------------------------------------------------------------------------------------------------------------------

级联删除这要找到数据库里的对象
用Emp emp=(Emp)session.get(Emp.class,7935");
  session.delete(emp);
这样会把emp表和相关联的dept表中的数据都删掉

-----------------------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------------------------------------------------------------------------

 

从表---主表, 一对多的关系 (Onetomany)
hibernate 之中的集合有 list,map,set,bag 在一对多中经常用的时set--原理:去空值,去重复 (难怪呢)
类之间用set实现1 对n
配置上,
<one-to-many>

<set 的属性有 :>
name 属性名 
table 基于关联表的一对多关系
lazy="true/false"是否使用延迟加载技术——不错!true,没有用到关联表,则不会把关联表的信息搜出来,加载到缓存中,反之则会严重影响其性能~ 平时就要检查设置为true hibernate 3.0以后基本默认都是true
inverse(true/false) 关联关系由哪一方来维护 true--会根据从表实体类维护 false--会根据主表实体类维护
out-join
fetch
orderby 对关联表排序
---
 <key column="设置从表的外键字段'></key>
   <one-to-many class="从表实体类"/>

dept和emp是 1对多的关系

1 将dept实体类中加入emps 的set集,然后get/set方法

只需要将dept.hbm.xml改下即可:

 

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!--   
  5.     Mapping file autogenerated by MyEclipse Persistence Tools  
  6. -->  
  7. <hibernate-mapping package="cn.com.csuinfosoft.vo">  
  8.     <class name="Dept" table="dept">  
  9.         <id name="deptno" column="deptno">  
  10.             <generator class="increment"></generator>  
  11.         </id>  
  12.         <property name="dname" column="dname"></property>  
  13.         <property name="loc" column="loc"></property>  
  14.           
  15.         <set name="emps" lazy="true" >  
  16.             <key column="deptno"></key>  
  17.             <one-to-many class="Emp"/>  
  18.         </set>  
  19.     </class>  
  20. </hibernate-mapping>  

 

 

 ----------------------------------------------------------------------------------------------------------------------------------------------

<many-to-many> 多对多
例子:学生表 关联表 老师表
<set >的属性
name
table 中间表
<key column="中间表的与当前表所映射的外键字段">
<many-to-many culumn="中间表与关系的另一个表所建立的关联字段">

这里给出一个写在一起的many-to-many.hbm.xml

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <hibernate-mapping package="cn.com.csuinfosoft.vo">  
  5.     <class name="Person" table="Person">  
  6.         <id name="personId" column="person_Id"></id>  
  7.         <property name="name" column="name"></property>  
  8.         <property name="age" column="age"></property>         
  9.         <set name="address" table="Person_Address">  
  10.             <key column="pa_personId"></key>  
  11.             <many-to-many class="Address" column="pa_addressId"></many-to-many>  
  12.         </set>  
  13.     </class>  
  14.   
  15.     <class name="Address" table="Address">  
  16.         <id name="addressId" column="address_Id"></id>  
  17.         <property name="addressInfo" column="address_Info"></property>  
  18.     </class>  
  19.       
  20. </hibernate-mapping>  

 

 

9.28 Hibernate 特殊表的关联 和  继承在hibernate 实现持久化的作用

1对1(外主)
1对多(中间表的)
继承,通过继承实现hibernate数据化的持久性操作

1对1关系
 第一种情况:a表引用b表的主键做外键具有唯一性约束
一个人对应一个地址
 person    address
-------------------
 p_id        a_id
 p_name      a_name
 a_id 外键+了唯一性约束
<many-to-one>
将many改成unique="true"
这个还是比较容易理解的。

 

 

第二中情况:a表引用b表的主键,在a表中既做主键,也做外键
person  address
----------------
p_id     a_id( 它是引用p_id的外键)
p_name   a_name
<one-to-one name="person" constrained="true"></one-to-one>只对主键进行描述

<one-to-one name="关联属性"> 在hibernate机制上描述两个实体1对1的关系
在操作时基于两个标的主键进行关联操作

基于该关系生成外键约束,或在某一键上加上某一属性
将contraonted="true"基于关系生成外键约束

column 描述关联字段(外键1对1关系,需要从主表这边描述的时候)

在它的<id 属性上>
  <genertor ,,
</id>

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <hibernate-mapping package="cn.com.csuinfosoft.oto">  
  5.     <class name="Person" table="o_person">  
  6.         <id name="pid" column="p_id">  
  7.             <generator class="increment"></generator>  
  8.         </id>  
  9.         <property name="pname"></property>  
  10.         <one-to-one name="address"></one-to-one>  
  11.     </class>  
  12.     <class name="Address" table="o_address">  
  13.         <id name="aid" column="a_id">  
  14.             <generator class="foreign">  
  15.                 <param name="property">person</param>  
  16.             </generator>  
  17.         </id>  
  18.         <property name="info"></property>  
  19.         <one-to-one name="person" constrained="true"></one-to-one>  
  20.     </class>  
  21. </hibernate-mapping>  

 

 

继承 在 hibernate中的作用
单表继承
在一个表中,通过一个标识来区分不同的数据类型,如type字段
用户有:学生,老师的例子不错啊
type属性 

<id...>
<discrimininator column="type类型的字段名 user_type">
</discrimininator>
<property...>
<subclass name="子类的名称" discriminator-value="标识字段为何值用该子类">
  <property name="teacherPhoto" column="teacher_photo"></property>
</subclass>

 继承在hibernate中的强势应用。这是单表的继承。
(类之间要有继承user被student 和teacher继承,配置如上)

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!--   
  5.     Mapping file autogenerated by MyEclipse Persistence Tools  
  6. -->  
  7. <hibernate-mapping package="cn.com.csuinfosoft.sub">  
  8.     <class name="User" table="sub_user_info">  
  9.         <id name="userId" column="user_id">  
  10.             <generator class="increment"></generator>  
  11.         </id>  
  12.         <discriminator column="user_type"></discriminator>  
  13.         <property name="userName" column="user_name"></property>  
  14.         <property name="userAge" column="user_Age"></property>  
  15.           
  16.         <subclass name="Teacher" discriminator-value="1">   
  17.             <property name="teacherPhoto" column="teacher_photo"></property>  
  18.         </subclass>  
  19.   
  20.         <subclass name="Student" discriminator-value="2">   
  21.             <property name="studentPhoto" column="student_photo"></property>  
  22.         </subclass>  
  23.     </class>  
  24. </hibernate-mapping>  

 

 

关联表的继承。
用户表是双方都有的信息
学生,老师是自己独有的基础信息表
         用户
           |
           |
----------------------------
学生                    老师

配置中用<joined-subclass>---继承关联
<joined-subclass name="类名" table="表名">
<key clumn="关联外键字段"/>
<property name="" clumn=""/>
<many-to-one>..</...>
</joined-subclass>

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!--   
  5.     Mapping file autogenerated by MyEclipse Persistence Tools  
  6. -->  
  7. <hibernate-mapping package="cn.com.csuinfosoft.joinsub">  
  8.     <class name="User" table="j_user">  
  9.         <id name="userId" column="user_id">  
  10.             <generator class="increment"></generator>  
  11.         </id>  
  12.         <property name="userName" column="user_name"></property>  
  13.         <property name="userPassword" column="user_Password"></property>  
  14.           
  15.         <joined-subclass name="Student">  
  16.             <key column="student_Id"></key>  
  17.             <property name="studentPhoto"></property>  
  18.         </joined-subclass>  
  19.   
  20.         <joined-subclass name="Teacher" ><!-- table="t_teacher" -->  
  21.             <key column="teacher_Id"></key>  
  22.             <property name="teacherPhoto"></property>  
  23.         </joined-subclass>  
  24.   
  25.     </class>  
  26. </hibernate-mapping>  

 

 

 

 在上面的特殊表关联中,要体会其原理,还有对 unique="true"的理解。。这个理解真的挺重要的。

-------------------------------------------------
会用hibernate做项目和你懂hibernate完全是两个概念。。  是的,知道原理,写起代码不再是机械式的填充。

 --------------------------------------------------------------------------------------------------------------------------------

hibernate 持久化对象的生命周期
session作为持久化对象 有3个状态:
1 瞬时状态--由new关键字创建生成的对象状态,这种对象只会在内存中存在
            状态没有和数据库同步
            session中没有持久该对象的引用。(数据对象有可能丢失)
2 持久状态--对象是由session创建生成(如session.save()   session.update())
            session持有该对象引用后,将其状态也入到数据库中
3 离线状态--原本为持久状态的对象,因session.close() 即 session资源的关闭或者session清空实体对象的            引用,导致该对象不再由session管理,称作离线状态

new(新生)----get/load()--》持久状态 session.load是按主键检索数据,创建持有对象,以及持久对象的代理对象,返回的是代理对象。
  |
  |
  |
瞬时状态   ----save(),saveOrUpdate() ----》持久状态 ---evict()清除指定类型id clear()清除所有 close()-----》离线状态

离线对象---update(),saveOrUpdate(),lock()-->持久对象-----delete()--》瞬时状态

hibernate每一个类都要配置一个id,表示唯一性。那么session的表示id也只有一个,因为唯一性的存在,反之,数据的维护变的相当混乱
---------------------------------------------------------------------------------
Hibernate 检索语言 Hql
"from 类名 where 属性名=? ";将查询的结果封装成类名所对应的类实例对象

hql的关联查询:
select a.dept.deptno from Emp a 会根据实体类之间的关联,自动生成多表关联的sql
from Emp a where a.dept.dname=?     hql果然强大~!

Query query=session.createQuery("from Emp a where a.dept.dname=?");
query.setString(0,"教育部");
List<Emp> result=query.list();

在hql中一旦出现select子句,它肯能查询出的结果不按照from的类名封装对象,而是将结果放在Object[]中

Query query=session.createQuery("select a.dept.dname.a.sal from Emp a where a.dept.dname=?");
query.setString(0,"教育部");
List<Object[]> result=query.list();

如果这样你用着还不是很爽,可以利用hibernate实现有参的构造函数
Query query=session.createQuery("select new Emp(a.dept.dname.a.sal) from Emp a where a.dept.dname=?");//前提Emp有这样一个构造函数。
query.setString(0,"教育部");
List<Emp> result=query.list();

------------------------hibernate的强大在于你可以根据自己的需求设计出合理的方式完成检索操作~赞一个!

hql函数的使用:
聚合函数:avg()  sum() max() count()
查询关键字:distinct
集合操作函数:size(),minelement(),minindex(),maxindex()
Orderby  子句   group by 子句

例子:"from Dept a where size(a.emps)>=2";
---------------------------------------------------
连接查询
inner join  基于关联属性经行操作       inner join fetch

Query query=session.createQuery("from Dept dept inner join fetch dept.emps");
query.list();

Left outer join                     left outer join fecth
Right outer hoin 
Fetch只对inner join 和Left join 有效,Right outer join返回的是数组

-----------------------------
Query query=session.getNamedQuery("leftjoin");//这个是在xml的配置文件中写的cdata..这个问题解决就好了
query.list();

 

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"  
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  4. <!--   
  5.     Mapping file autogenerated by MyEclipse Persistence Tools  
  6. -->  
  7. <hibernate-mapping package="cn.com.csuinfosoft.vo">  
  8.     <class name="Emp" table="emp">  
  9.         <id name="empno" column="empno">  
  10.             <generator class="increment"></generator>  
  11.         </id>  
  12.         <property name="ename" column="ename"></property>  
  13.         <property name="job" column="job"></property>         
  14.         <property name="mgr" column="mgr"></property>         
  15.         <property name="hireDate" column="hiredate"></property>                       
  16.         <property name="sal" column="sal"></property>     
  17.         <property name="comm" column="comm"></property>  
  18.           
  19.         <many-to-one name="dept" column="deptno" outer-join="true" cascade="all">       
  20.         </many-to-one>  
  21.     </class>  
  22.     <query name="leftjoin">  
  23.         <!--[CDATA[  
  24.             from Emp emp left join fetch emp.dept  
  25.         ]]-->  
  26.     </query>  
  27. </hibernate-mapping>  

 

 

---------------------------------------------------------------------------------------------------------------

补充的知识:
标准查询
SQL查询
附:拦截器
    验证器
    锁策略--乐观锁,悲观锁的操作实现


标准查询---面向对象技术//这个没有sql,或者hql语句灵活,也没他们可读性强。这种语言只能作为辅助
 sql---------->对象的方法
Criteria cr=session.createCriteria(Emp.class);
cr.add(Expression.gt("sal",1000));//Expression是一个接口关于Criteria
List result=cr.list();
Emp emp=null;
for(int i=0;i<result.size();i++){
  emp=(Emp)result.get(i);
}


标准查询是基于Critera.add(查询条件)    查询条件由Experssion生成对象,根据不同的条件方法调度,生成对应的查询条件  Experssion方法有很多(eq,gt,like等)

-------------------
SQl 查询
sql语句的通用性很差。不同的版本oracle会使用到不同的sql语句语法。容易出错。 了解下了
而HQL则无需考虑这些。
SQLQuery sqlQuery=session.createSQLQuery("select ename,job,sal from emp where deptno=?");
Query query=session.getNamedQuery("leftjoin");//这个是在xml的配置文件中写的cdata..
sqlQuery.setInteger(0,10);
List list=sqlQuery.list();

-----------------------

拦截器--设置在sessionFactory之上,对session的持久化操作就行拦截
EmptyInterceptor  是个抽象类,我们的类需要实现它。
加入方法用eclipse的 overwrite中找到对应的方法即可!!!
onDelete()
onLoad()
onSave()
这是继承EmptyInterceptor 的类例如MyInterceptor
那么在实现类中 加入
Configuration  configuration = new Configuration().configure();
configuration.setInterceptor(new MyInterceptor())//这个是加入的。。!!!
SessionFactory sessionFactory = configuration.buildSessionFactory();
------------------------------------
验证器
验证接口--用于在数据的添加,修改时,在持久化操作之前,对数据有效性验证。
validator---validate() throws ValidationFailure
validate()可以终止原有的持久化操作。

-----------------------------------
锁策略 
锁机制 ---在并发访问下,保护资源有序的被使用
乐观锁  悲观锁
Hibernate 锁策略

Hibernate 内部锁机制

LockMode.NONE 无锁机制

LockMode.WRITE  hibernate 进行保存和更新时自动使用的锁机制。

LockMode.READ hibernate 读取纪录时的机制

悲观锁

整个数据处理过程中,将数据处于锁定
状态。悲观锁的实现,往往依靠数据库提供的锁机制

LockMode.UPGRADE

LockMode.UPGRADE_NOWAIT

 //相当于SQL(for update  中的 wait 或者nowaite)

实现机制如下:

Criteria.setLockMode

Query.setLockMode(Strng指hql语句中实体类的别名,LockMode.UPGRADE);
例如:
Query query=session.createQuery("from Emp a");
Query.setLockMode(a,LockMode.UPGRADE_NOWAIT);

Emp emp=(Emp)session.load(Emp.class,1,LockMode.UPGRADE_NOWAIT);//悲观锁

session.lock (实例对象,LockMode.READ);
缺点:资源开销大,一般不用这种,通常推荐使用乐观锁机制

乐观锁

更加宽松的加锁机制,悲观锁对长事务而言,开销往往无法承受;避免死锁。

实现机制:
Hibernate在o/R中映射特殊字段<timestamp>  或者<version>
采用特殊字段来做判断,平时操作不等待,但是保存或者更新时会进行判断。


Version

Dirty

ALL

主要介绍 Version

官方推荐的乐观锁实现策略,广泛使用,具有经验可借鉴性

实现举例:在每一次进行读取操作时取出版本号,在进行更新时同时刷新版本号,更新时只能更新低版本的数据,从而完成锁策略。 Hibernate 的 Session 会在等待用户交互时 ,Session 断开数据库连接。在整个应用事务过程中, Hibernate 使用单例 Session 和单例类来实现。

使用方法:

<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">

< 主键 >

<version name="version"  column="version"   type="java.lang.Integer"  /> 

同时数据库表中增加字段  version ,version无须设置,它会随着操作自动增加。

总结:在一般性的事务中,大可将锁机制抛开不用,这样不可否认增加了复杂性,你不得不面对不少的版本异常信息,只有在涉及关键业务如进行网上购物的付款等就必须进行加锁管理,当然推荐基于 version 的乐观锁管理。

 

-------------------------------------------------------------------------------------------------------------

hibernate 空值异常
     
     字段 ---》属性(基本数据类型)(包装类型,字符,日期)
  基本数据类型(int,double,char等)
        优:性能好
      缺点:不能接受空字段的值
  包装类:如Double,String,Date,Integer(就是java.lang.*这种包装类)
        优:能包装空值在内的所有有效数值
      缺点:资源开销大

提示:如果数据封装不上pojo类,有可能就是数据类型选择的错误!
----------------------------------------------------------------------------
这样的错误:
<c:forEach var="dt" items="${requestScope.list}">
   <tr>
  <td>${dt.empno}</td>
  <td>${dt.ename}</td>
  <td>${dt.job}</td>
  <td>${dt.sal}</td>
  <td>${dt.dept.deptno}</td>//可以显示的,它在emp表中作为外键<many-to-one name="dept".. ><column

name="DEPTNO"/></many-to-one>
  <td>${dt.dept.dname}</td>//这个不可以显示,它跟emp无任何关联。是dept独有的。会报session已经关闭。以下

有解决办法。
  </tr>
</c:forEach>

session是线程不安全,不能被多个线程同时使用
web-线程->请求处理  一个请求可以对应一个session线程。

利用java.lang.ThreadLocal  会为每一个当前线程分配一个独立的存储空间
Map<key,value>会为这一个线程保存独有的线程信息
以下为代码:
--------------------------------------------------------
view plaincopy to clipboardprint?
package cn.com.csuinfosoft.hibernate;  
 
import org.hibernate.Session;  
import org.hibernate.SessionFactory;  
import org.hibernate.cfg.Configuration;  
 
public class HibernateUtil {  
 
 private static SessionFactory sessionFactory = null;  
   
 private static ThreadLocal threadLocal = new ThreadLocal();  
   
 static {  
  try {  
   Configuration config = new Configuration().configure();  
   sessionFactory = config.buildSessionFactory();  
  } catch (Exception ex) {  
   ex.printStackTrace();  
  }  
 }  
   
 public static Session getSession() {  
  Session session = (Session)threadLocal.get();//获取当前线程对应的内存空间中,存储的对象  
  if(session == null) {  
   session = sessionFactory.openSession();  
   threadLocal.set(session);  
  }  
  return session;  
 }  
   
 public static void closeSession() {  
  Session session = (Session)threadLocal.get();  
  if(session != null) session.close();  
  threadLocal.set(null);  
 }  
   

package cn.com.csuinfosoft.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

 private static SessionFactory sessionFactory = null;
 
 private static ThreadLocal threadLocal = new ThreadLocal();
 
 static {
  try {
   Configuration config = new Configuration().configure();
   sessionFactory = config.buildSessionFactory();
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }
 
 public static Session getSession() {
  Session session = (Session)threadLocal.get();//获取当前线程对应的内存空间中,存储的对象
  if(session == null) {
   session = sessionFactory.openSession();
   threadLocal.set(session);
  }
  return session;
 }
 
 public static void closeSession() {
  Session session = (Session)threadLocal.get();
  if(session != null) session.close();
  threadLocal.set(null);
 }
 
}
 
//在实现类中通过 Session session=HibernateUtil.getSession()这样得到的session是在同一个请求中保持不变的


然后当我们需要在请求结束关闭这样个一session可以写filter文件:
-------------------------
view plaincopy to clipboardprint?
package cn.com.csuinfosoft.filter;  
 
import java.io.IOException;  
 
import javax.servlet.Filter;  
import javax.servlet.FilterChain;  
import javax.servlet.FilterConfig;  
import javax.servlet.ServletException;  
import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;  
 
import cn.com.csuinfosoft.hibernate.HibernateUtil;  
 
public class HibernateFilter implements Filter {  
 
 public void destroy() {  
 
 }  
 
 public void doFilter(ServletRequest request, ServletResponse response,  
   FilterChain filterChain) throws IOException, ServletException {  
  try {  
   System.out.println("============ Filter try ====== Thread:" +   
 
Thread.currentThread().getName());  
   filterChain.doFilter(request, response);  
  } finally {  
   System.out.println("============ Filter finally ======Thread:" +   
 
Thread.currentThread().getName());  
   HibernateUtil.closeSession(); //每次请求结束前关闭Session  
  }  
    
 }  
 
 public void init(FilterConfig filterConfig) throws ServletException {  
    
 }  
 

package cn.com.csuinfosoft.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import cn.com.csuinfosoft.hibernate.HibernateUtil;

public class HibernateFilter implements Filter {

 public void destroy() {

 }

 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain filterChain) throws IOException, ServletException {
  try {
   System.out.println("============ Filter try ====== Thread:" +

Thread.currentThread().getName());
   filterChain.doFilter(request, response);
  } finally {
   System.out.println("============ Filter finally ======Thread:" +

Thread.currentThread().getName());
   HibernateUtil.closeSession(); //每次请求结束前关闭Session
  }
 
 }

 public void init(FilterConfig filterConfig) throws ServletException {
 
 }

}

 

最后将这样一个filter配置在web.xml中,是相当容易的。
----------------------------

 
补充:SessionFactory可以在监听器控制下, 是要在程序卸载的时候关闭掉。

在过去所学的线程中Thread 中获得当前线程方法为currentThread()

 hibernate的配置优化
<property name="jdbc.batch_size">30</property>   这个用于管理数据库批量处理的,如批量删除
<property name="jdbc.fetch_size">50</property> 在jdbc抓取数据时采用分批抓取,一次可以抓取50条

做一个简单 批量删除 实现,不是很难哦!

 

----------------------------------------------------------------------------------------------------------------

不懂得问题:

<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">

< 主键 >

<version name="version"  column="version"   type="java.lang.Integer"  /> 

</class>

 

解释下schema="SPRINGDEV" 和optimistic-lock="version":

1)其中<class name="UserVo" table="uservo" schema="SPRINGDEV" optimistic-lock="version">中的schema="SPRINGDEV"表示数据库的用户名。如果当前链接数据库的用户名称不是SPRINGDEV的话,实际操作中还是会用SPRINGDEV这个用户来操作。这就会产生一系列问题。

 

2)optimistic-lock属性有如下可选取值:
? none 无乐观锁
? version 通过版本机制实现乐观锁
? dirty 通过检查发生变动过的

 

-------------------------------------------------------------------------------------------------------------------------

 

Hibernate 关闭sessionFactory :

  关闭sessionFactory是应在服务器被关闭,程序被卸载时关闭,所以需要写一个sessionFactory特有的监听类,当服务器被关闭时,自动关闭sessionFactory.
写个监听类 实现ServletContextListener 在该类中关闭关闭sessionFactory ,以下就是:

 

  1. package cn.com.csuinfosoft.listener;  
  2.   
  3. import javax.servlet.ServletContextEvent;  
  4. import javax.servlet.ServletContextListener;  
  5.   
  6. import cn.com.csuinfosoft.hibernate.HibernateUtil;  
  7.   
  8. public class HibernateListener implements ServletContextListener {  
  9.   
  10.     public void contextDestroyed(ServletContextEvent arg0) {  
  11.         HibernateUtil.closeSessionFactory();  
  12.     }  
  13.   
  14.     public void contextInitialized(ServletContextEvent arg0) {  
  15.   
  16.     }  
  17.   
  18. }  

 

 


将监听类配置在web.xml 中


 <listener>
  <listener-class>cn.com.csuinfosoft.listener.HibernateListener</listener-class>
 </listener>

 

 -------------------------------------------------------------------------------------

 

---------------------------------------------------------------以下转载的,一些关键字的注意,配合着学习:

重点学习 Hibernate fetch lazy cascade inverse 关键字

 

Hibernate最让人头大的就是对集合的加载形式。
书看了N次了,还是没有真正理解Hibernate。所以下午专门做了下测试,对配置文件的意思加深了认识。

假设有两个表,Photos(一) --- picture(多)Photo包含picture集合

结论1: HQL代码 > fetch(配置) > lazy (配置)
结论2: 默认 lazy="true"
结论3: fetch 和 lazy 主要是用来级联查询的,   而 cascade 和 inverse 主要是用来级联插入和修改的

             fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查 询; 而join方式,主体对象和关联对象用一句外键关联的sql同时查询出来,不会形成多次查询。
如果你的关联对象是延迟加载的,它当然不会去查询关联对象。 另外,在hql查询中配置文件中设置的join方式是不起作用的(而在所有其他查询方式如get、criteria或再关联获取等等都是有效的),会使用select方式,除非你在hql中指定join fetch某个关联对象。fetch策略用于定义 get/load一个对象时,如何获取非lazy的对象/集合。 这些参数在Query中无效。

在某种特殊的场合下,fetch在hql中还是起作用的。
例如
现有message(回帖)-->topic(主贴)-->forum(版块) 的多级many-to-one结构:
第一级:message-->topic many-to-one配置lazy="false" fetch="join"
第二级:topic-->forum many-to-one配置lazy="false" fetch="join"
这时如果"from message",则第二级:topic-->forum中的fetch策略会起作用

查询抓取(默认的)在N+1查询的情况下是极其脆弱的,因此我们可能会要求在映射文档中定义使用连接抓取:

<set name="permissions"
fetch="join">
<key column="userId"/>
<one-to-many class="Permission"/>
</set
<many-to-one name="mother" class="Cat" fetch="join"/>
在映射文档中定义的抓取策略将会有产生以下影响:

通过get()或load()方法取得数据。

只有在关联之间进行导航时,才会隐式的取得数据(延迟抓取)。

条件查询

在映射文档中显式的声明 连接抓取做为抓取策略并不会影响到随后的HQL查询。

通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特定的事务中, 使用HQL的左连接抓取(left join fetch) 对其进行重载。这将通知 Hibernate在第一次查询中使用外部关联(outer join),直接得到其关联数据。 在条件查询 API中,应该调用 setFetchMode(FetchMode.JOIN)语句。


其实这并不能说明hql能够按照配置文件设置的join进行抓取,这时 第二级:topic-->forum 的抓取其实已经和hql没有关系了,因为前面已经产生了另一个select方式的抓取语句。
而是对象的关联获取,假如查询message时topic是设置为延迟加载的,那么在后面获取message.topic时,如topic.forum不延迟加载,那么topic-->forum会实现配置的join方式的抓取,这个显然和hql查询没有关系。

结论4: 如果你是用spring来帮你管理你的session, 并且是自动提交,延迟加载就等于没加载~_~(当然
                除非你手动重新打开session然后手动Hibernate.initialize(set);然后关闭session.
结论5:      cascade主要是简化了在代码中的级联更新和删除。
j结论6:老爸可以有多个孩子,一个孩子不能有多个老爸,而且老爸说的算, 孩子围着老爸转。
                所以Photos老爸要有权力所以 cascade 这个关键子都是送给老爸的, 也就是级联更新,
               老爸改姓了,儿子也得跟着改,呵呵。“不然,就没有零花钱咯”。
                而Picture儿子整体挨骂,但是还是要维护父子之间良好的关系,对老爸百依百顺,所
               以老爸就说,儿子,“关系,由你来维护(inverse="true") ,不然就不给零花钱。呵。”。
               <set name="pictures" inverse="true" cascade="all">
                    <key>
                       <column name="photosid" not-null="true" />
                    </key>
                 <one-to-many class="girl.domain.Picture" />
             </set>
               
测试代码:

    Photos p = ps.getById(1);
   Set<Picture> set = p.getPictures();
   for(Picture pic : set){
    System.out.println(pic.getId());
   }

配置文件的一部分:
       <set name="pictures" inverse="true" cascade="all" >
            <key>
                <column name="photosid" not-null="true" />
            </key>
            <one-to-many class="girl.domain.Picture" />
        </set>

测试过程会对配置文件不断修改:并且从来不曾手动重新打开session

测试结构:

当配置条件为 lazy=true 一句查询 测试代码中没有调用getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

lazy=true 一句查询 有getPicture()
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?


lazy=true 一句查询 有getPicture() 并且访问了里面的元数Picture 且有异常抛出
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?


lazy="false" 两句查询 肯定没问题,因为全部数据都个查了出来 所以怎么调用都正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?
Hibernate: select pictures0_.photosid as photosid1_, pictures0_.id as id1_, pictures0_.id as id2_0_, pictures0_.photosid as photosid2_0_, pictures0_.name as name2_0_, pictures0_.clicked as clicked2_0_, pictures0_.uploaddate as uploaddate2_0_, pictures0_.size as size2_0_, pictures0_.description as descript7_2_0_, pictures0_.uri as uri2_0_ from super.picture pictures0_ where pictures0_.photosid=?


fetch="join" 一句查询 效果 == lazy="false" 呵呵,哪个效率高,我就不知道了。。。。。。。。。。。
Hibernate: select photos0_.id as id0_1_, photos0_.userid as userid0_1_, photos0_.typeid as typeid0_1_, photos0_.name as name0_1_, photos0_.createtime as createtime0_1_, photos0_.description as descript6_0_1_, photos0_.faceid as faceid0_1_, photos0_.uri as uri0_1_, pictures1_.photosid as photosid3_, pictures1_.id as id3_, pictures1_.id as id2_0_, pictures1_.photosid as photosid2_0_, pictures1_.name as name2_0_, pictures1_.clicked as clicked2_0_, pictures1_.uploaddate as uploaddate2_0_, pictures1_.size as size2_0_, pictures1_.description as descript7_2_0_, pictures1_.uri as uri2_0_ from super.photos photos0_ left outer join super.picture pictures1_ on photos0_.id=pictures1_.photosid where photos0_.id=?

不加fetch="join" 一句查询 没有getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

不加fetch="join" 一句查询 有getPicture() 正常
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

不加fetch="join" 一句查询 有getPicture() 并且访问里面的元素Picture的ID 有异常抛出
Hibernate: select photos0_.id as id0_0_, photos0_.userid as userid0_0_, photos0_.typeid as typeid0_0_, photos0_.name as name0_0_, photos0_.createtime as createtime0_0_, photos0_.description as descript6_0_0_, photos0_.faceid as faceid0_0_, photos0_.uri as uri0_0_ from super.photos photos0_ where photos0_.id=?

来个两兵交战 fetch="join" lazy="true" 呵呵 结果,一句查询, 结构正常 所以就当lazy不存在好了。 看来fetch 是老大。、、、、、、、、、、、、、
Hibernate: select photos0_.id as id0_1_, photos0_.userid as userid0_1_, photos0_.typeid as typeid0_1_, photos0_.name as name0_1_, photos0_.createtime as createtime0_1_, photos0_.description as descript6_0_1_, photos0_.faceid as faceid0_1_, photos0_.uri as uri0_1_, pictures1_.photosid as photosid3_, pictures1_.id as id3_, pictures1_.id as id2_0_, pictures1_.photosid as photosid2_0_, pictures1_.name as name2_0_, pictures1_.clicked as clicked2_0_, pictures1_.uploaddate as uploaddate2_0_, pictures1_.size as size2_0_, pictures1_.description as descript7_2_0_, pictures1_.uri as uri2_0_ from super.photos photos0_ left outer join super.picture pictures1_ on photos0_.id=pictures1_.photosid where photos0_.id=?

分享到:
评论

相关推荐

    SSH之Hibernate总结

    SSH之Hibernate总结 SSH(Struts、Spring、Hibernate)是Java Web开发中常见的三大框架,而Hibernate作为ORM(对象关系映射)框架,是连接Java应用程序与数据库的关键组件。本总结将围绕Hibernate的核心概念、配置...

    Hibernate总结

    【Hibernate总结】 Hibernate是一个强大的Java持久化框架,它封装了JDBC,负责对象持久化,作为应用程序和数据库之间的中间层。映射关系是通过配置文件维护的,这使得Hibernate能够与不同的数据库系统灵活地交互。 ...

    hibernate总结练习源码

    本资源包含的"hibernate总结练习源码"提供了对Hibernate ORM框架实际应用的实例,有助于深入理解和掌握其核心概念与功能。 1. **对象关系映射(ORM)**:Hibernate 提供了一种机制,将数据库中的表映射为Java类,表...

    Hibernate总结(三)

    《Hibernate总结(三)》 在本篇关于Hibernate的总结中,我们将深入探讨这个流行的Java对象关系映射(ORM)框架的关键概念和技术细节。Hibernate作为一款强大的工具,它极大地简化了Java开发人员处理数据库操作的工作...

    hibernate 总结

    标题:hibernate总结 描述:此文档是个人在使用Hibernate框架进行数据持久化操作时的经验积累和技巧分享。文档全面覆盖了Hibernate的各种配置方法、数据映射技术、集合类映射、对象关系映射(ORM)基础以及与J2EE...

    学习HIbernate总结

    ### 学习Hibernate总结 #### 一、简介与配置 Hibernate是Java环境下一款优秀的对象关系映射(ORM)框架,它极大地简化了数据访问层(DAL)的编码工作,允许开发人员将主要精力集中在业务逻辑上而不是繁琐的SQL语句...

    jdbc_Hibernate总结

    1. 引入Hibernate所需的JAR文件,例如在Eclipse中创建Hibernate类库。 2. 创建配置文件`hibernate.cfg.xml`,其中包含数据库连接信息、日志格式等。 3. 设计实体类,对应数据库表中的记录,并提供对应的getter和...

    hibernate 总结 附 项目

    **总结项目实战** 在实际项目中,使用 Hibernate 可以简化数据库操作,提高开发效率。常见的应用场景包括用户管理、订单处理、商品分类等。项目实践中要注意合理设计实体关系,避免 N+1 查询问题,利用缓存优化性能...

    Hibernate总结——课程管理

    在Java开发中,Hibernate是一个非常重要的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据。本教程将深入探讨如何使用Hibernate来实现一个简单的课程管理系统,涵盖多对...

    jdbc和hibernate总结

    总结来说,JDBC是基础的数据库访问技术,适合进行简单的数据库操作,而Hibernate则通过提供面向对象的接口,极大地简化了数据库操作,尤其适用于复杂的业务场景。两者结合使用,可以让开发者在享受面向对象编程便利...

    Hibernate4总结文档

    《Hibernate4总结文档》 Hibernate4作为一款强大的Java对象关系映射框架,简化了数据库操作,使得开发者可以更专注于业务逻辑而不是数据库层面的细节。本文将深入探讨Hibernate4的配置和使用,帮助开发者更好地理解...

    hibernate文档总结,技术汇总,PDF版的,hibernate简明参考文档

    总结来说,Hibernate是一个强大的ORM框架,它极大地简化了Java应用的数据库操作,提高了开发效率,并提供了高级特性如缓存、事务管理等。通过深入理解和熟练使用Hibernate,开发者可以构建更高效、更易于维护的...

Global site tag (gtag.js) - Google Analytics