千里马

天马行空

Hibernate总结

1,任何的计算机程序都是由指令和数据两部分组成,持久化数据对于对于大多数程序,尤其是企业级应用程序,是必不可少的。数据的持久化,,也就是把数据保存起来,并且可以供程序获取这些数据的全部和某一部分。对于java程序来说,有3个持久化数据的途径:文本文件、对象的序列化和数据库。
文本持久化数据对于数据量少和数据结构单一的情况比较好。如果数据量大,由于IO的操作速度比内存的操作速度要慢得多,会造成很大的性能问题。另外,如果数据的结构太复杂,简单的符号相隔 的形式实在难于满足数据的粗去功能。
对象的序列化可以满足数据结构复杂的存取,但是还是很难解决数据量大的问题。而且,它也很难满足大多数企业级程序所需要的检索功能。
关系数据库是目前数据持久化最成熟的产品,也是java程序首选的数据持久化的解决方案。它能够存取海量的数据,提供高性能的数据检索功能,大多数的数据库厂商也提供了java的jdbc驱动。但是,如果使用jdbc来操作数据库,会有以下几项不可避免的弊端:
(1),数据操作的代码量巨大。
(2),重复劳动的装填数据。
(3),面向对象的思想和关系模型之间的冲突。
2,Hibernate基础:
  Hibernate是一个开放源代码的对象关系映射框架,它对jdbc进行了轻量级的对象封装,使得java程序员可以随心所欲的使用面向对象编程思想来操作数据库。Hibernate可以应用在任何使用jdbc的场合,既可以在普通的java程序中使用,也可以在javaweb 应用程序中使用,还可以在EJB容器中使用,完成数据持久化的任务,极大地减轻了程序员的数据层工作。
Hibernate就好像在java程序和数据库之间的一座桥梁,它提供了丰富的API供程序员使用,当程序员通过这些API操作数据对象的时候,Hibernate会自动完成于数据库之间的数据同步,还有跨数据库的作用。
Hibernate的底层实现依然是jdbc,但是程序员已经看不到任何jdbc的影子了,它提供给开发者的是另外一套API。数据库操作的基本单元是表格,而ORM技术操作的基本单元是实体对象,所有Hibernate持久化数的操作方式又是一种全新的模式。Hibernate的5个重要的接口:Session、SessionFactory、Configuration、Transaction和Query,他们同时也是Hibernate最核心的组成概念。
(1),Session接口:负责执行被持久化对象的添加、删除、查询、修改操作,有点类似与jdbc的Connection和Statement,他代表了java程序与数据库之间的一次交流。需要注意的是,Session对象时非线程安全的,一般来说,一个线程包含一个Session对象。
(2),SessionFactory是产生Session的工厂类,他负责为java程序创建Session。一般来说,一个SessionFactory代表了一个数据源,当需要操作多个数据库时,可以为每个数据库制定一个SessionFactory。一般情况,一个项目通常只需要一个SessionFactory就行了。
(3),Configuration接口负责Hibernate的配置工作,创建SessionFactory对象。在Hibernate的启动过程中,Configuration类的实例定位映射文件的位置、读取配置,然创建SessionFactory对象。
(4)Transaction接口负责事务的相关操作,它代表的Hibernate的事务,本质上也是数据库事务。Transaction是可选的,开发者也可以设计编写自己的底层事务处理代码。
(5),Query接口负责各种数据查询功能,他也可以使用Hibernate特有的HQL语言和SQL语言两种方式。
 以上这5个API接口是几乎所有Hibernate程序都会使用到的,也是程序员使用Hibernate进行开发的基础。他们之间的关系大致是这样的:首先,有Configuration获取配置信息并做一些初始化的工作;接着,Configuration创建SessionFactory;再通过SessionFactory创建Session;然后程序就使用Session完成一般的添加、删除、查询、修改操作了;如果需要使用复杂一点的查询功能,则可以通过Session获取Query,执行查询操作。如果需要使用事务Transaction,也是在Session的范围内使用。
3,使用Hibernate的一般步骤: 
  (1),Hibernate所需的jar文件盒配置文件。
       要使用Hibernate,首先,把Hibernate所需的jar文件存放到java程序的类加载路径里面;另外就是准备好Hibernate的配置文件。
  手动搭建Hibernate开发环境:
 1》,赋值所需的jar文件到java程序的类加载路径下,对于web应用程序则复制到“WEB-INF/lib”目录下。
 2》,为java程序准备一个Hibernate配置文件。一般情况下,文件名:hibernate.cfg.xml,存放在类加载路径下,对web应用程序则存放在“WEB-INF/classes”里面。hibernate.cfg.xml的主要配置就是SessionFactory,它包括数据库连接URL、数据库别名、包含的实体和其他一些Hibernate工具等信息。该配置文件的内容是和Configuration接口相对应的,往往的应用程序只有一哥这样的配置文件。:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

<session-factory>
       <!-- 数据库别名 -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <!-- JDBC连接URL -->
 <property name="connection.url">jdbc:mysql://localhost:3306/test</property>
 <!-- 数据库用户名 -->
 <property name="connection.username">root</property>
 <!-- 数据库密码 -->
 <property name="connection.password">123</property>
 <!-- 数据库JDBC驱动类名 -->
 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 <!-- 显示sql语句 -->
  <property name="show_sql">true</property>
  <!-- 自动建表设置 -->
    <property name="hbm2ddl.auto">create</property>
    <!-- 需要与数据库进行ORM映射的实体 -->
    <mapping resource="com/insigma/User.hbm.xml"/>
</session-factory>

</hibernate-configuration>
对于Hibernate工具,指的是为了方便程序员的开发和调研,hibernate提供的是一些可选的功能,下面是三个常用的Hibernate工具:
  show_sql 让hibernate把底层执行的sql语句打印在控制台上。   <property name="show_sql">true</property>
  format_sql 自动格式化打印到控制台上的sql语句           <property name="format_sql">true</property>
  hbm2ddl.auto 用于自动创建数据库表。通过它,在Hibernate每次使用之前,他会更具实体及他们之间的关系自动创建表或更改表结构。                                           <property name="hbm2ddl.auto">create</property>
(2),创建POJO实体:
   实体,是ORM技术范畴的一个重要概念,它代表兑现现实世界的某种事物的抽象模拟,例如,用户、学生、动物等。实体是Hibernate的基本操作单元,在开发者眼里实体就是一个数据对象,而且该数据对象是需要保存到数据库里的。
Hibernate操作的实体是简单的java对象,与EJB的实体bean不同,POJO实体不需要继承任何类和实现任何接口,他就是一个最普通的java对象,它的定义方式和javabean优点类似,也需要包含一个公开的默认的无参构造方法,也是使用setter和getter方法访问实体的属性。
实体代表的是一类事物,那么每个实体靠什么区分开呢?与数据库表格的主键类似,,实体也有主键,而且必须有一个主键,Hibernate会根据主键的相等与否区别实体对象。另外主键是一般没有业务意义的,他仅仅用来区分不同的实体对象,常用java.lang.Lang型来定义实体对象的主键的。
(3),创建数据库表:
      1》手动创建。
       2》通过对hibernate.cfg.xml的配置,自动创建实体对应的表格需要加上这样的配置:   <property name="hbm2ddl.auto">create</property> 在Hibernate每次使用之前,他会更具实体及他们之间的关系自动创建表或更改表结构。  当然的他的底层实现还是需要用到create等DML语言的SQL语句。
(4),映射配置文件:
  映射配置文件是指明实体与数据库之间是如何映射的,他负责告诉Hibernate从java程序到数据库应该怎样保存数据,以及如何从数据库取出数据到java程序里。一般情况下,一个实体就对应一个映射配置文件。实体之间的关系也是在配置文件中进行相应配置的。
映射配置文件时采用XML格式,其内容大致是这样的,在跟标签<hibernate-mapping>里使用<class>标签配置实体类,通过《class》标签的name属性指定实体的完整类名,table指定表名,在《class》标签里,必须使用《id》配置实体的主键和生成策略,然后使用《property》标签配置实体其他属性的映射。另外,还有可能使用《many-to-one》《set》等标签配置实体与其他实体的关系。
                                     映射配置文件常用的XML标签及其使用介绍
标签                 属性                           说明
<class>              name                       实体类名
                    table                     实体对应的数据库表名
<id>               name                          实体的主键属性名
                    column                       数据库表的主键字段名,默认与name相同
<generator>           class                   主键生成策略
<property>            name                    实体的属性名
                      column                       数据库表的对应的字段名,默认与name相同
                       not-null                      是否为空,默认可以
                         unique                       是否唯一,默认否
                       length                         字段的最大长度
<one-to-one>                                           一对一
<many-to-one>                                           多对一
<many-to-many>                                           多对多
<set>                                                用来建立集合映射
(5)使用Hibernate API 操作数据:
    一切准备就绪以后,就可以使用Hibernate提供给开发者的API的操作实体数据了。程序员使用到的主要接口和类都在org.hibernate包里。
package com.insigma;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
public class HibernateSessionFactory {
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
private static final ThreadLocal<Session> threadLocal = new ThreadLocal<Session>();
private  static Configuration configuration = new Configuration();   
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;
     static {
     try {
   configuration.configure(configFile);
   sessionFactory = configuration.buildSessionFactory();
  } catch (Exception e) {
   System.err
     .println("%%%% Error Creating SessionFactory %%%%");
   e.printStackTrace();
  }
    }
    private HibernateSessionFactory() {
    }
public static Session getSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
  if (session == null || !session.isOpen()) {
   if (sessionFactory == null) {
    rebuildSessionFactory();
   }
   session = (sessionFactory != null) ? sessionFactory.openSession()
     : null;
   threadLocal.set(session);
  }

        return session;
    }
public static void rebuildSessionFactory() {
  try {
   configuration.configure(configFile);
   sessionFactory = configuration.buildSessionFactory();
  } catch (Exception e) {
   System.err
     .println("%%%% Error Creating SessionFactory %%%%");
   e.printStackTrace();
  }
 }
public static void closeSession() throws HibernateException {
        Session session = (Session) threadLocal.get();
        threadLocal.set(null);

        if (session != null) {
            session.close();
        }
    }
 public static org.hibernate.SessionFactory getSessionFactory() {
  return sessionFactory;
 }
public static void setConfigFile(String configFile) {
  HibernateSessionFactory.configFile = configFile;
  sessionFactory = null;
 }
 public static Configuration getConfiguration() {
  return configuration;
 }
}
从以上代码基本可以看出,使用Hibernate的步骤与jdbc有些类似,大致可以分为6步:
1》生成配置对象(Configuration)。通过调用Configuration的configure() 方法,用配置文件的设置创建配置对象,一般情况下,配置对象只需要一个。
2》创建SessionFactory对象。有配置对象创建一个SessionFactory对象,它代表了一个数据源。他的作用有一点类似于jdbc的驱动管理器,用来打开Session。一般情况,SessionFactory对象也只需一个。
3》代开session。Hibernate的Session代表了一次与数据库的连接,程序员需要的大多数操作都需要通过它。Session自带了一个缓存,无论是否利用Session进行数据的添加、删除、等都要经过缓存。
4》利用Session进行各种实体操作。保存一个实体对象,可以调用Session的save(),persist(),saveorupdate()方法。HIbernate首先把没有主键的实体保存保存在缓存里,然后在事务提交或调用Session.flush()方法以后把实体数据同步到数据库里。
对于修改一个实体对象的数据,如果程序是在Session关闭之前修改的,无需调用任何方法。否则,可以调用Session的update(),merge()saveOrUpdate()方法,进行实体的重新保存。
删除实体简单,直接调用Session的dele()方法即可。
当需要查询实体时,使用Session的get()和load()方法或通过Session.createQuery()产生Query对象,执行查询语句。无论用什么方式得到的实体,都会首先放在Session缓存里。
5》事务处理.一般来说,除了查询之外,其他的实体操作都需要使用到事务。开始-》提交-》(异常)回滚
6》关闭Session。与JDBC关闭数据库一样。Session的关闭会让Hibernate及时的把缓存里的数据同步到数据库中。
4,ID生成策略:
 主键ID,是实体的唯一标示符,它与数据库的主键相对应。主键对于Hibernate是至关重要的,例如当程序调用Session.saveOrUpdate()方法的时候,Hibernate会以主键标准去缓存里找实体对象是否存在。如果存在则执行更新操作,否则执行新增操作。所以,保证实体是主键的唯一是Hibernate许多的工作基础。
主键的生成策略需要在实体映射配置文件中指定:常用的ID生成策略有:native、increment、sequence、assigned、identify、hilo、foreign
(1)native:根据数据库本地的生成策略生成主键。例如,Oracle采用Sequence,Mysql和sqlserver采用identify,也就是将主键的生成工作交给数据库完成,Hibernate不做任何管理。
(2),increment:插入数据的时候Hibernate会给主键添加一个自增的主键,一个Hibernate实例就维护一个计数器,所以在多个实例运行的时候就不能使用这个方法。
(3)Sequence调用数据库的sequence来生成主键,要设定序列名,不然hibernate无法找到,一般针对oracle使用。
(4)assigned插入数据的时候主键有程序自己添加,hibernate不做任何管理。
(5),identify:自增字段功能。不适合Oracle
(6),该策略称作高低策略,它是保障生成的结果具有唯一性的算法。需要在数据库中建立一张额外的表,默认的表明为 hibernate_unique_key,默认的字段为integer类型名称为,next_hi也可以通过配置指定表名和字段名。
(7),采用外键来生成主键,表的主键是其他表的外键,也就是用其他表的外键来生成自己的表的主键。该策略常用与一对一的映射关系。
5,关系映射:关系映射指的是实体之间的关系与数据库表之间的关系相互对应的过程。建立关系映射之后,当程序员操作这些实体以及与之有关联的实体的时候,就可以吧关系的操作同步到数据库中,数据库则一般表现为外键的各种操作。
三种映射关系:一对一、一对多,多对多
6,继承映射:
继承关系是面向对象思想的特有关系,而数据库不存在继承关系。如果要把程序里的继承关系映射到数据库,,就需要用主外键的关系模拟这种继承关系。一般情况下,用Hibernate建立继承关系的映射,可以有两种解决方案,各有优点,应该根据不同的情况采用不同的映射策略。
(1)单表实现:单表继承映射的时候,只需要定义一个映射配置文件就行了。
  单表是实现继承映射的优点在于:没有任何的表连接,查询的速度回相对较快,多台查效率高。但是他把所有的数据都存放在一张表里,有可能导致表特别大,不利于后期维护,而且子类的属性很多,可能会有很多的null值,所以单表实现继承映射更适合数据量小,,属性个数小或多台查询比较多的情况。
(2)每个子类一张表实现:优点在于数据存储的比较紧凑,当查询某个子类数据时比较快。但是由于有很多的连接,不太适合多台查询,更适合侧重操作某一类数据的情况。所以多表实现的继承映射比较适合数据量大、子类属性个数多或经常查询某一子类的情况。
7,实体对象的生命周期:
实体。作为数据的一种装载单元,他在Hibernate的管理过程中,回不断的发生数据和状态的变化。Hibernate不仅仅是一个ORM的API工具,他还是一个容器,他可以帮你管理实体对象的生命周期,这个容器就是Session的缓存。
Hibernate实体对象的三种状态:瞬时态、持久态、托管态。实体对象的状态会随着Hibernate的API的调用而发生变化,开发者也应该根据实体对象的状态的不同而使用不同的API。
 瞬时态:有new语句开辟内存空间的心Jjava对象。如果没有没有变量对该对象进行引用,他将被java虚拟机回收。
瞬时对象在内存孤立,它是携带信息的载体,不和数据库的数据有任何的关联关系。最大的特点没有主键。在Hibernate中,可通过Session的save()或saveOrUpdte()等方法将瞬时对象和数据库关联,并将数据同步到数据库中。此时该瞬时对象转化为持久化对象。
持久态:处于持久态的对象在数据库中具有对应的记录,并有一个持久化标志。如果是用Session的delete()方法,对应的持久对象,就变成瞬时对象,因数据库中的对应数据已被删除,该对象不再关联数据库中任何的记录。当执行Session的close clear、evict方法之后,此时持久对象变成托管对象仍具有数据库识别值。他已不再Hibernate持久层的管理之下了。持久对象具有两个特点:具有主键且数据库中肯定有响应的记录。
托管态:当与某持久对象关联的Session被关闭之后,持久变脱托管。当托管对象被重新关联到Session上时,转变为持久。托管对象具有数据库的识别值。可通过update,saveOrUpdate方法转变为持久对象。特点:本质上和瞬时对象一样,在没有任何变量引用的时候,jvm会在适当的时候回收,但是拥有主键。
8,Hibernate中的查询功能:hibernate提供的实体查询功能是非常强大的,他不仅可以完成一般sql可以完成的功能,还可以智能的帮助开发者完成一些工作,例如自动填充数据,关联加载、跨数据库实现分页查询等
(1)用get()和load()方法获取单个实体对象
        根据主键去查询实体,是最常见也是最简单的查询。使用Hibernate非常简单,只需要调用get()和load()方法即可。他们的参数列表相同,第一个是实体的类型或完整类名,第二个是主键。查询得到的实体对象,都进入持久态。尽管两种方法作用类似,但是意义却有些不同。get是去数据库获取实体对象,没有放回null而load()的意义在于把指定主键的实体对象加载到缓存里。如果没有的话,Hibernate抛出ObjectNotFoundException异常。
(2)HQL查询语言
HQL是Hibernate提供给开发者以面向对象的思想进行实体添加、删除、等操作的查询语言,他看起来和sql比较相似,但是它提供了更加丰富和灵活的查询特性,同时也提供了面向对象的封装。
1,实体查询:
最简单的实体查询就是直接使用from加实体名。
String hql=“from User”;
List list=Session.CreateQuery(hql).list();
HQL与标准SQl相似,也可以在HQl语句中使用where,并且可以再where字句中使用表达式、比较操作符、以及使用and、or连接不同查询条件的组合。
2,实体的更新和删除。
与sql优点类似
开始事务
String hql=“”;
Query q=Session.CreateQuery(hql);
int ret=q.executeUpdate();
提交事务
3,属性查询:
有的时候,检索数据并不需要获得实体对应的全部数据,而只需检索出实体对应的部分数据,这时就可以利用HQL的属性查询你技术:
4,排序和分组:
(1)order by子句
与sql语句相似,HQL查询语句也可以使用order by子句对查询结果进行排序,并且可以通过asc和desc关键字指定排序方式。
(2)group by 子句和统计查询
在HQl语句中同样支持使用group by子句分组查询。还支持group by子句结合聚集函数的分组统计查询。大部分标准的聚集函数都可以在HQL语句中使用。
5,参数绑定:
Hibernate对动态参数绑定提供了丰富的支持,HQL也像JDBC的Preparedstatement一样,也可以只用占位符实现参数动态绑定。而且提供了更丰富的特性。在Hibernate中共提供了3中参数绑定方式。
(1)按参数名绑定。
 在HQl语言中,定义命名参数使用“:”开头;
(2)用?来定义参数的位置
(3)setparameter()方法
5,分页查询
Hibernate实现分页查询的功能支持非常好,可以说程序员使用分页查询是傻瓜式的,简单到了极致,只需通过调用两个方法告诉Hibernate从哪行开始和最多的行数其他的细节就交给Hibernate了。
6,延迟加载

延迟加载是Hibernate关联关系的实体对象默认的加载方式,延迟加载机制是为避免一些无谓的性能开销而提出来的。所谓的延迟加载就是在真正需要数据的时候,才真正执行数据加载操作,可以简单的理解为,只用在使用的时候,才发出sql语句进行查询。
延迟加载第一种保障性能的技术,不一定要使用。可以通过在映射文件里进行设置不使用延迟加载。

posted on 2012-06-15 19:43 Mr Lee 阅读(1280) 评论(0)  编辑  收藏


只有注册用户登录后才能发表评论。


网站导航:
 

My Links

Blog Stats

常用链接

留言簿

随笔分类

随笔档案

文章档案

(hibernate)http://www.blogjava.net/dyllove98/archive/2012/05/12/377959.html

搜索

最新评论

阅读排行榜

评论排行榜