当前位置:首页>>开发编程>>JAVA>>新闻内容  
Hibernate的原理与配置快速入门
作者:罗小虎编译 发布时间:2004-10-27 9:06:05 | 【字体:

  也许你听说过Hibernate的大名,但可能一直不了解它,也许你一直渴望使用它进行开发,那么本文正是你所需要的!在本文中,我向大家重点介绍Hibernate的核心API调用库,并讲解一下它的基本配置。

  看完本文后,我相信你对什么是ORM(对像/关系映射)以及它的优点会有一个深刻的认识,我们先通过一个简单的例子开始来展现它的威力。

  正如一些传统的经典计算机文章大都会通过一个“hello,world”的例子开始讲解一样,我们也不例外,我们也将从一个相对简单的例子来阐述Hibernate的开发方法,但如果要真正阐述Hibernate的一些重要思想,仅仅靠在屏幕上打印一些字符是远远不够的,在我们的示例程序中,我们将创建一些对象,并将其保存在数据库中,然后对它们进行更新和查询。

“Hello World” “Hello world”示例程序让您对Hibernate有一个简单的认识
理解Hibernate的架构 介绍Hibernate接口的主要功能。
核心接口 Hibernate有5个核心接口,通过这几个接口开发人员可以存储和获得持久对象,并且能够进行事务控制
一个重要的术语:Type Type是Hibernate发明者发明的一个术语,它在整个构架中是一个非常基础、有着强大功能的元素,一个Type对象能将一个Java类型映射到数据库中一个表的字段中去。
策略接口 Hibernate与某些其它开源软件不同的还有一点――高度的可扩展性,这通过它的内置策略机制来实现。
基础配置 Hibernate可以配置成可在任何Java环境中运行,一般说来,它通常被用在2-3层的C/S模式的项目中,并被部署在服务端。
创建一个SessionFactory对象 要创建一个SessionFactory对象,必须在Hibernate初始化时创建一个Configuration类的实例,并将已写好的映射文件交由它处理。

  “Hello World”

  Hibernate应用程序定义了一些持久类,并且定义了这些类与数据库表格的映射关系。在我们这个“Hello world”示例程序中包含了一个类和一个映射文件。让我们看看这个简单的持久类包含有一些什么?映射文件是怎样定义的?另外,我们该怎样用Hibernate来操作这个持久类。

  我们这个简单示例程序的目的是将一些持久类存储在数据库中,然后从数据库取出来,并将其信息正文显示给用户。其中Message正是一个简单的持久类:,它包含我们要显示的信息,其源代码如下:

  列表1 Message.Java 一个简单的持久类

package hello;
public class Message {
 private Long id;
 private String text;
 private Message nextMessage;
 private Message() {}
 public Message(String text) {
  this.text = text;
 }
 public Long getId() {
  return id;
 }
 private void setId(Long id) {
  this.id = id;
 }
 public String getText() {
  return text;
 }
 public void setText(String text) {
  this.text = text;
 }
 public Message getNextMessage() {
  return nextMessage;
 }
 public void setNextMessage(Message nextMessage) {
  this.nextMessage = nextMessage;
 }
}


  Message类有三个属性:Message的id 、消息正文、以及一个指向下一条消息的指针。其中id属性让我们的应用程序能够唯一的识别这条消息,通常它等同于数据库中的主键,如果多个Message类的实例对象拥有相同的id,那它们代表数据库某个表的同一个记录。在这里我们选择了长整型作为我们的id值,但这不是必需的。Hibernate允许我们使用任意的类型来作为对象的id值,在后面我们会对此作详细描述。

  你可能注意到Message类的代码类似于JavaBean的代码风格,并且它有一个没有参数的构造函数,在我们以后的代码中我将继续使用这种风格来编写持久类的代码。

  Hibernate会自动管理Message类的实例,并通过内部机制使其持久化,但实际上Message对象并没有实现任何关于Hibernate的类或接口,因此我们也可以将它作为一个普通的Java类来使用:

Message message = new Message("Hello World");
System.out.println( message.getText() );


  以上这段代码正是我们所期望的结果:它打印“hello world”到屏幕上。但这并不是我们的最终目标;实际上Hibernate与诸如EJB容器这样的环境在持久层实现的方式上有很大的不同。我们的持久类(Message类)可以用在与容器无关的环境中,不像EJB必须要有EJB容器才能执行。为了能更清楚地表现这点,以下代码将我们的一个新消息保存到数据库中去:

Session session = getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
Message message = new Message("Hello World");
session.save(message);
tx.commit();
session.close();


  以上这段代码调用了Hibernate的Session和Transaction接口(关于getSessionFactory()方法我们将会马上提到)。它相当于我们执行了以下SQL语句:

insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)
values (1, 'Hello World', null)


  在以上的SQL语句中,MESSAGE_ID字段到底被初始化成了什么值呢?由于我们并没有在先前的代码中为message对象的id属性赋与初始值,那它是否为null呢?实际上Hibernate对id属性作了特殊处理:由于它是一个对象的唯一标识,因此当我们进行save()调用时,Hibernate会为它自动赋予一个唯一的值(我们将在后面内容中讲述它是如何生成这个值的)。

  我们假设你已经在数据库中创建了一个名为MESSAGE的表,那么既然前面这段代码让我们将Message对象存入了数据库中,那么现在我们就要将它们一一取出来。下面这段代码将按照字母顺序,将数据库中的所有Message对象取出来,并将它们的消息正文打印到屏幕上:

Session newSession = getSessionFactory().openSession();
Transaction newTransaction = newSession.beginTransaction();
List messages =newSession.find("from Message as m order by m.text asc");
System.out.println( messages.size() + " message(s) found:" );
for ( Iterator iter = messages.iterator(); iter.hasNext(); ) {
 Message message = (Message) iter.next();
 System.out.println( message.getText() );
}
newTransaction.commit();
newSession.close();


  在以上这段代码中,你可能被find()方法的这个参数困扰着:"from Message as m order by m.text asc",其实它是Hibernate自己定义的查询语言,全称叫Hibernate Query Language(HQL)。通俗地讲HQL与SQL的关系差不多就是方言与普通话之间的关系,咋一看,你会觉得它有点类似于SQL语句。其实在find()调用时,Hibernate会将这段HQL语言翻译成如下的SQL语句:

select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
from MESSAGES m
order by m.MESSAGE_TEXT asc


  以下就是运行结果:

1 message(s) found:
Hello World


  如果你以前没有ORM(对象-关系映射)的开发经验,那你可能想在代码的某个地方去寻找这段SQL语句,但在Hibernate中你可能会失望:它根本不存在!所有就SQL语句都是Hibernate动态生成的。

  也许你会觉得还缺点什么,对!仅凭以上代码Hibernate是无法将我们的Message类持久化的。我们还需要一些更多的信息,这就是映射定义表!这个表在Hibernate中是以XML格式来体现的,它定义了Message类的属性是怎样与数据库中的MESSAGES表的字段进行一一对应的,列表2是这个示例程序的映射配置文件清单:

  列表2:示例程序的对象-关系映射表

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="hello.Message" table="MESSAGES">
 <id name="id" column="MESSAGE_ID">
  <generator class="increment"/>
 </id>
 <property name="text" column="MESSAGE_TEXT"/>
 <many-to-one name="nextMessage" cascade="all" column="NEXT_MESSAGE_ID"/>
</class>
</hibernate-mapping>


  以上这个文档告诉Hibernate怎样将Message类映射到MESSAGES表中,其中Message类的id属性与表的MESSAGE_ID字段对应,text属性与表的MESSAGE_TEXT字段对应,nextMessage属性是一个多对一的关系,它与表中的NEXT_MESSAGE_ID相对应。

  相对于有些开源项目来说,Hibernate的配置文件其实是很容易理解的。你可以轻松地修改与维护它。只要你定义好了持久类与数据库中表字段的对应关系就行了,Hibernate会自动帮你生成SQL语句来对Message对象进行插入、更新、删除、查找工作,你可以不写一句SQL语句,甚至不需要懂得SQL语言!

  现在让我们做一个新的试验,我们先取出第一个Message对象,然后修改它的消息正文,最后我们再生成一个新的Message对象,并将它作为第一个Message对象的下一条消息,其代码如下:

  列表3 更新一条消息

Session session = getSessionFactory().openSession();
Transaction tx = session.beginTransaction();
// 1 is the generated id of the first message
Message message =(Message) session.load( Message.class, new Long(1) );
message.setText("Greetings Earthling");
Message nextMessage = new Message("Take me to your leader (please)");
message.setNextMessage( nextMessage );
tx.commit();
session.close();


  以上这段代码在调用时,Hibernate内部自动生成如下的SQL语句:

select m.MESSAGE_ID, m.MESSAGE_TEXT, m.NEXT_MESSAGE_ID
from MESSAGES m
where m.MESSAGE_ID = 1

insert into MESSAGES (MESSAGE_ID, MESSAGE_TEXT, NEXT_MESSAGE_ID)
values (2, 'Take me to your leader (please)', null)

update MESSAGES
set MESSAGE_TEXT = 'Greetings Earthling', NEXT_MESSAGE_ID = 2
where MESSAGE_ID = 1


  当第一个Message对象的text属性和nextMessage被程序修改时,请注意Hibernate是如何检测到这种变化,并如何在数据库中自动对它更新的。这实际上是Hibernate的一个很有价值的特色,我们把它称为“自动脏数据检测”,Hibernate的这个特色使得当我们修改一个持久对象的属性后,不必显式地通知Hibernate去将它在数据库中进行更新。同样的,当第一个Message对象调用setNextMessage()方法将第二个Message对象作为它的下一条消息的引用时,第二条消息会无需调用save()方法,便可以自动地保存在数据库中。这种特色被称为“级联保存”,它也免去了我们显式地对第二个Message对象调用save()方法之苦。

  如果我们再运行先前的那段将数据库中所有的Message对象都打印出来的代码,那它的运行结果如下:

2 message(s) found:
Greetings Earthling
Take me to your leader (please)


  “Hello world”示例程序现在介绍完毕。我们总算对Hibernate有了一个简单的认识,下面我们将回过头来,对Hibernate的主要API调用作一下简要的介绍:


[首页]    [上一页]    [下一页]    [末页]    

文章来源:天极网
·JDBC+Hibernate将Blob数据写入Oracle
 放生
 愚爱
 够爱
 触电
 白狐
 葬爱
 光荣
 画心
 火花
 稻香
 小酒窝
 下雨天
 右手边
 安静了
 魔杰座
 你不像她
 边做边爱
 擦肩而过
 我的答铃
 怀念过去
 等一分钟
 放手去爱
 冰河时代
 你的承诺
 自由飞翔
 原谅我一次
 吻的太逼真
 左眼皮跳跳
 做你的爱人
 一定要爱你
 飞向别人的床
 爱上别人的人
 感动天感动地
 心在跳情在烧
 玫瑰花的葬礼
 有没有人告诉你
 即使知道要见面
 爱上你是一个错
 最后一次的温柔
 爱上你是我的错
 怎么会狠心伤害我
 不是因为寂寞才想
 亲爱的那不是爱情
 难道爱一个人有错
 寂寞的时候说爱我