Hibernate总结3

实例状态:

PO的三个状态:瞬态,持久化,脱管(离线)

 

1、(瞬态)未被持久化的VO

此时就是一个内存对象VO,由JVM管理生命周期

 

2、(持久化)已被持久化的PO,并且在Session生命周期内

此时映射数据库数据,由数据库管理生命周期

 

3、(脱管)曾被持久化过,但现在和Session已经detached了,以VO的身份在运行

这种和Session已经detached的PO还能够进入另一个Session,继续进行PO状态管理,此时它就成为PO的第二种状态了。这种PO实际上是跨了Session进行了状态维护的。

 

在传统的JDO1.x中,PO只有前面两种状态,一个PO一旦脱离PM,就丧失了状态了,不再和数据库数据关联,成为一个纯粹的内存VO,它即使进入一个新的PM,也不能恢复它的状态了。

 

 

Hibernate缓存介绍:

缓存在Hibernate中主要有三个方面:一级缓存、二级缓存和查询缓存。

一级缓存

      Hibernate的一级缓存是由Session提供的,因此它只存在于Session的生命周期中,也就是当Session关闭的时候该Session所管理的一级缓存也会立即被清除,所以也可以理解为一级缓存是session缓存

       Hibernate的一级缓存是Session所内置的,不能被卸载,也不能进行任何配置。

       一级缓存采用的是key-valueMap方式来实现的,在缓存实体对象时,对象的主关键字IDMapkey,实体对象就是对应的值。所以说,一级缓存是以实体对象为单位进行存储的,在访问的时候使用的是主关键字ID

       虽然,Hibernate对一级缓存使用的是自动维护的功能,没有提供任何配置功能,但是可以通过Session中所提供的方法来对一级缓存的管理进行手工干预。Session中所提供的干预方法包括以下两种。

●   evict() :用于将某个对象从Session的一级缓存中清除。

●   clear() :用于将一级缓存中的对象全部清除。

       在进行大批量数据一次性更新的时候,会占用非常多的内存来缓存被更新的对象。这时就应该阶段性地调用clear()方法来清空一级缓存中的对象,控制一级缓存的大小,以避免产生内存溢出的情况。具体的实现方法如清单14.8所示。

       清单14.8    大批量更新时缓存的处理方法

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

for ( int i=0; i<100000; i++ ) {

    Customer customer = new Customer(……);

    session.save(customer);

    if ( i % 20 == 0 ) {

        //将本批插入的对象立即写入数据库并释放内存

        session.flush();

        session.clear();

    }

}

tx.commit();

session.close();

 

 

Hibernate查询方法与缓存的关系

       在前面介绍了Hibernate的缓存技术以及基本的用法,在这里就具体的Hibernate所提供的查询方法与Hibernate缓存之间的关系做一个简单的总结。

       在开发中,通常是通过两种方式来执行对数据库的查询操作的。一种方式是通过ID来获得单独的Java对象,另一种方式是通过HQL语句来执行对数据库的查询操作。下面就分别结合这两种查询方式来说明一下缓存的作用。

       通过ID来获得Java对象可以直接使用Session对象的load()或者get()方法,这两种方式的区别就在于对缓存的使用上。

●   load()方法

       在使用了二级缓存的情况下,使用load()方法会在二级缓存中查找指定的对象是否存在。

在执行load()方法时,Hibernate首先从当前Session的一级缓存中获取ID对应的值,在获取不到的情况下,将根据该对象是否配置了二级缓存来做相应的处理。

       如配置了二级缓存,则从二级缓存中获取ID对应的值,如仍然获取不到则还需要根据是否配置了延迟加载来决定如何执行,如未配置延迟加载则从数据库中直接获取。在从数据库获取到数据的情况下,Hibernate会相应地填充一级缓存和二级缓存,如配置了延迟加载则直接返回一个代理类,只有在触发代理类的调用时才进行数据库的查询操作。

       Session一直打开的情况下,并在该对象具有单向关联维护的时候,需要使用类似Session.clear()Session.evict()的方法来强制刷新一级缓存。

●   get()方法

       get()方法与load()方法的区别就在于不会查找二级缓存。在当前Session的一级缓存中获取不到指定的对象时,会直接执行查询语句从数据库中获得所需要的数据。

       Hibernate中,可以通过HQL来执行对数据库的查询操作。具体的查询是由Query对象的list()iterator()方法来执行的。这两个方法在执行查询时的处理方法存在着一定的差别,在开发中应该依据具体的情况来选择合适的方法。

●   list()方法

       在执行Querylist()方法时,Hibernate的做法是首先检查是否配置了查询缓存,如配置了则从查询缓存中寻找是否已经对该查询进行了缓存,如获取不到则从数据库中进行获取。从数据库中获取到后,Hibernate将会相应地填充一级、二级和查询缓存。如获取到的为直接的结果集,则直接返回,如获取到的为一些ID的值,则再根据ID获取相应的值(Session.load()),最后形成结果集返回。可以看到,在这样的情况下,list()方法也是有可能造成N次查询的。

       查询缓存在数据发生任何变化的情况下都会被自动清空。

●   iterator()方法

       Queryiterator()方法处理查询的方式与list()方法是不同的,它首先会使用查询语句得到ID值的列表,然后再使用Sessionload()方法得到所需要的对象的值。

       在获取数据的时候,应该依据这4种获取数据方式的特点来选择合适的方法。在开发中可以通过设置show_sql选项来输出Hibernate所执行的SQL语句,以此来了解Hibernate是如何操作数据库的。

 

 

Hibernate:乐观锁,悲观锁。

悲观锁:是基于数据库锁的机制实现的,只支持单个事务的操作,有一个事务在操作时别的事务操作就不能进行。

session.load(Person.class, "ID", LockMode.UPGRADE);

乐观锁:支持多个事务操作。是采用数据库版本机制实现的

<class name="包名.类名" table="表名" optimistic-lock="version">

           <id name="id">   

               <generator class="uuid.hex" />

           </id>

           <version name="version"/>

           <property name="属性名" />

    </class>

注:version在数据进行更改时会自动加一

 

使用hibernate 操作oracle:

Hibernate连接Oracle数据库的步骤
hibernate.cfg.xml需要改动两处地方

1.       数据库连接驱动:oracle.jdbc.driver.OracleDriver

2.       方言org.hibernate.dialect.OracleDialect

 

Hibernate 原始sql的另一种查询方法命名查询
<sql-query name="persons">
    <return alias="person" class="erson"/>
    SELECT
          person.person_id  AS {person.id},
          person.NAME AS {person.name},
           person.AGE AS {person.age}
        
    FROM PERSON person
</sql-query>
Hibernate
调用Oracle函数

  <sql-query name="名字" callable="true">
      <return alias="person" class="erson">
    <return-property name="id" column="person_id"/>
    <return-property name="name" column="name"/>
    <return-property name="age" column="age"/>
    </return>
          {?=call oracle
函数名
()}
  </sql-query>

Hibernate的事务:

Hibernate JDBC 的轻量级封装,本身并不具备事务管理能力。在事务管理层,
Hibernate
将其委托给底层的JDBC或者JTA,以实现事务管理和调度功能。

Hibernate
的默认事务处理机制基于JDBC Transaction

 

 

 

抓取策略:连接.查询.子查询.批量

1.连接抓取(Join fetching - Hibernate通过 SELECT语句使用OUTER JOIN(外连接)来获得对象的关联实例或者关联集合。一个对象一条SQl语句.

  <set name="students" inverse="true" cascade="all" fetch="join">

            <key column="classid" />

            <one-to-many class="com.Student" />

  </set>

 

  Classes cla = (Classes)session.load(Classes.class,1);

  System.out.println(cla.getName());

  for(Iterator iter = cla.getStudents().iterator();iter.hasNext();){

       Student student = (Student)iter.next();

       System.out.println(student.getName());

   }

   Fetch=join ,上面程序只发了一条sql语句.

 

2.查询抓取(Select fetching - 另外发送一条 SELECT 语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。在上面的程序中会发出当前对象关联的集合的大小+1sql语句.

 

3.子查询抓取(Subselect fetching - 另外发送一条SELECT 语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。除非你显式的指定lazy="false" 禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条

  select语句。所有最多只会发出两条SQL语句. 如果只有一个对对象则JoinSubselect没有区别.如果是多个则Join查询次数为对象的个数而Subselect则只有一条sql语句.

 

4.批量抓取(Batch fetching - 对查询抓取的优化方案, 通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。

  <set name="students" inverse="true" cascade="save-update" batch-size=”3”>

  List students = session.createQuery(“select s from Student s where s.id in(1,2,3,4,5,6,7,8).list();

  for(Iterator iter=students.iterator();iter.hasNext();){

       Student student = (Sutdent)iter.next();

       System.out.println(student.getName());

       System.out.println(student.getClassess().getName());

   }  

  当第二个for循环时,每次加载 之前设置的 数量 实体对象,  如:现在设置3,那么当

  Iterator iter=students.iterator();

  iter.hasNext();时候,他会查询出3student对象

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值