Hibernate 的原理与配置

网络编程 2025-04-05 06:46www.168986.cn编程入门

【导读】你是否听说过Hibernate的大名却对其知之甚少,或者一直渴望使用它进行开发?那么,这篇文章正是你期待已久的宝典!本文将重点介绍Hibernate的核心API调用库和基本配置,通过一系列介绍,让你对ORM(对象/关系映射)及其优点有深刻的认识。

【初探Hibernate】

让我们从一个简单的例子开始,展现Hibernate的魅力。如同众多经典计算机文章从“hello, world”的例子入手,我们的示例程序也将从相对简单的场景出发,阐述Hibernate的开发方法。要真正了解Hibernate的核心思想,仅仅在屏幕上打印字符是远远不够的。在我们的示例中,我们将创建对象,并将其保存在数据库中,然后进行更新和查询。

【阅读导航】

一、 “Hello World”示例程序:让你对Hibernate有一个简单的认识。

二、 理解Hibernate的架构:介绍Hibernate接口的主要功能。

三、 核心接口:Hibernate有5个核心接口,通过这些接口,开发人员可以存储和获取持久对象,并进行事务控制。

四、 重要的术语Type:Type是Hibernate中的一个基础而强大的元素,一个Type对象能将Java类型映射到数据库表的字段中。

五、 策略接口:Hibernate与某些其他开源软件不同的还有一点——高度的可扩展性,这通过其内置的策略机制来实现。

六、 基础配置:Hibernate可以配置成可在任何Java环境中运行,通常被用在2-3层的C/S模式的项目中,并被部署在服务端。

接下来,我们将详细这些内容。

【“Hello World”示例程序详解】

这个简单的持久类Message包含了一些属性,如id、文本内容、以及指向下一条消息的指针。其中,id属性用于唯一标识每条消息,通常对应数据库中的主键。如果多个Message实例拥有相同的id,那么它们代表数据库表的同一个记录。

Message类的代码遵循JavaBean的代码风格,并且有一个无参数的构造函数。在后续的代码中,我们将继续沿用这种风格来编写持久类的代码。

通过Hibernate,我们可以方便地操作这些持久类,将其实例存储在数据库中,并从数据库中查询出来,将信息展示给用户。这个过程将涉及到Hibernate的核心API调用和配置。

【总结】

本文向你介绍了Hibernate的核心概念和基本配置,通过一个简单的“Hello World”示例程序,展示了Hibernate的开发方法。通过深入了解Hibernate的架构、核心接口、Type术语、策略接口以及基础配置,你将能够更轻松地使用Hibernate进行开发。在接下来的文章中,我们将继续深入Hibernate的更多高级特性和使用方法。Hibernate是一个强大的对象关系映射工具,它能将Java对象与数据库无缝地连接起来。在这个特殊的场景中,我们有一个名为Message的普通Java类,Hibernate会自动管理这个类的实例,并将其持久化到数据库中,尽管Message类并没有实现任何特定的Hibernate类或接口。

创建一个新的Message实例就像这样:

```java

Message message = new Message("Hello World");

System.out.println(message.getText());

```

这段代码会打印出“Hello World”,这正是我们期望的结果。我们的目标不仅仅是如此。Hibernate与EJB容器等环境在持久层的实现上有显著的不同。我们的持久类(如Message类)可以在与容器无关的环境中使用,不像EJB那样必须依赖特定的容器才能运行。

为了展示这一点,让我们看一下如何将新的消息保存到数据库中。代码片段如下:

```java

Session session = getSessionFactory().openSession();

Transaction tx = session.beginTransaction();

Message message = new Message("Hello World");

session.save(message);

txmit();

session.close();

```

```sql

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

```

你可能会问,MESSAGE_ID字段被初始化为多少呢?因为我们并没有为message对象的id属性赋予初始值。实际上,Hibernate会对id属性进行特殊处理。作为一个对象的唯一标识,当我们调用save()方法时,Hibernate会自动为它赋予一个唯一的值。这个值的生成方式将在后面的内容中详细介绍。

假设你已经在数据库中创建了一个名为MESSAGE的表。现在,你已经将Message对象存入数据库中了,接下来是如何将它们检索出来。以下代码将按照消息正文的字母顺序,从数据库中检索所有的Message对象,并将它们打印到屏幕上。

在这个过程中,你可能会对find()方法的参数感到困惑:“from Message as m order by m.text asc”。这是Hibernate自己的查询语言,全称为Hibernate Query Language(HQL)。通俗地讲,HQL与SQL的关系就像是方言与普通话之间的关系。在find()调用时,Hibernate会将这段HQL语言翻译成相应的SQL语句来执行。

最终的运行结果会是:

```vbnet

1 message(s) found:

Hello World

```

所有的SQL语句都是Hibernate幕后生成的精彩之作。或许你会觉得仅仅依靠代码Hibernate无法将Message类永久保存。确实如此,我们还需要更多的信息,那就是映射定义表。这个表在Hibernate中是以XML格式呈现的,它详细说明了Message类的属性是如何与数据库中的MESSAGES表的字段一一对应的。让我们看一下示例程序的映射配置文件清单。

示例程序的对象关系映射表是这样的:

这份文档向Hibernate揭示了如何将Message类映射到MESSAGES表中。例如,Message类的id属性与表的MESSAGE_ID字段相对应,text属性与表的MESSAGE_TEXT字段相对应,而nextMessage属性则展示了一个多对一的关系,它与表中的NEXT_MESSAGE_ID字段相对应。与其他开源项目相比,Hibernate的配置文件其实更容易理解。你可以轻松修改和维护它。只需定义好持久类与数据库中表字段的对应关系,Hibernate就会自动为你生成SQL语句,对Message对象进行增删改查操作。你甚至可以不需要写一句SQL语句,甚至不需要懂得SQL语言!

现在让我们做个小实验。我们先取出第一个Message对象,然后修改它的消息正文,再创建一个新的Message对象,并将其作为第一个Message对象的下一条消息。以下是相关的代码:

Session session = getSessionFactory().openSession();

Transaction tx = session.beginTransaction();

// 1 是第一条消息的生成id

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);

txmit();

session.close();

如果我们运行一段代码来打印数据库中所有的Message对象,我们会发现结果清晰明了,例如:“2条消息找到:Greetings Earthling,Take me to your leader (please)”。通过这个简单的示例,我们对Hibernate有了初步的认识。接下来,我们将深入了解Hibernate的主要API调用。

在理解Hibernate的架构时,首先要熟悉其编程接口。Hibernate的API设计简洁明了,尽管由于ORM的复杂性,其API并不简单。但别担心,我们不需要一下子了解所有的接口。在应用层与持久层之间,应用层充当了持久层的客户端角色。但在某些简单的项目中,这两层并没有严格的区分。在这种情况下,你可以将它们合并为一层。

Hibernate的接口可以分为几种类型:一是用户应用程序调用的接口,用于完成创建、读取、更新、删除和查询操作,如Session、Transaction和Query接口;二是用于读取配置文件的接口,如Configuration类;三是回调接口,允许应用程序对事件的发生作出响应;四是用于扩展Hibernate映射机制的接口,如UserType、CompositeUserType和IdentifierGenerator。

在Hibernate中,JDBC、JTA和JNDI等J2EE技术得到了广泛应用。JDBC作为支持关系数据库操作的基础层,与JNDI和JTA结合,使Hibernate能方便地集成到J2EE应用服务器中。虽然在这里我们无法详细讨论Hibernate API中的所有方法,但我们可以简要介绍每个主要接口的功能。如果你想了解更多,可以查阅Hibernate源码包中的相关子包。

核心接口中的Session接口是Hibernate开发人员最常用的接口之一。它是一个轻量级的类,创建和销毁成本低,适合在客户程序中频繁创建和销毁。Session可以看作是一个持久对象的缓冲区,能够检测到这些持久对象的改变并刷新数据库。有时我们也称Session为持久层管理器,因为它包含了一些与持久层相关的操作,如将持久对象存储到数据库以及从数据库中获取它们。值得注意的是,Hibernate的Session不同于JSP应用中的HttpSession。在开发过程中保持对Session的正确管理是非常重要的。通过理解并有效使用这些核心接口,我们能够更加高效地使用Hibernate进行开发。当我们Hibernate中的session时,我们主要关注的是其核心的session功能。session这个词在使用时特指Hibernate中的数据会话,而对于Http Sesion对象,我们通常称之为用户session。

我们来看SessionFactory接口。这个接口遵循了工厂模式的设计原则。用户程序通过SessionFactory来创建session的实例。尽管SessionFactory并不是轻量级的,但它的设计初衷是为了在整个应用中实现共享。在实际应用中,一个项目往往只需要一个SessionFactory即可满足需求。当项目需要与多个数据库交互时,每个数据库对应一个SessionFactory。

SessionFactory在Hibernate中起到了缓冲的作用,存储了Hibernate自动生成的SQL语句和其他映射数据,甚至包括未来可能重复利用的数据。这种设计有效提升了数据的处理效率。

接着是Configuration接口,它的主要作用是对Hibernate进行配置和启动。在Hibernate启动过程中,Configuration类的实例负责定位映射文档,读取配置信息,并创建SessionFactory对象。虽然它在整个Hibernate项目中扮演的角色较小,但却是启动Hibernate时不可或缺的部分。

再来说说Transaction接口。这是一个可选的API,你可以选择使用Hibernate底层的事务处理代码,或者实现自己的事务管理。Transaction接口是对实际事务的抽象,包括JDBC事务、JTA中的UserTransaction,甚至是CORBA事务。这样的设计使得开发者可以使用统一的事务操作界面,方便项目在不同环境和容器之间迁移。

至于Query和Criteria接口,它们为数据库查询提供了便利。Query接口支持HQL语言或本地数据库的SQL语句,可以绑定查询参数、限制查询记录数量,并执行查询操作。Criteria接口与Query接口类似,允许你创建并执行面向对象的标准化查询。值得注意的是,Query接口是轻量级的,必须在session的上下文中使用。

另外还有一个重要的术语——Type。在Hibernate架构中,Type是一个基础而强大的元素。一个Type对象能将Java类型映射到数据库表的字段中。这种设计使得Hibernate具有高度灵活性和扩展性。Hibernate内置了许多type类型,包括所有的Java基本类型,并且还支持用户自定义type。通过实现UserType和CompositeUserType接口,你可以创建自己的type,如Address、Name等,从而提升项目的便利性和代码优雅性。

除了上述接口和术语,Hibernate还有Callback接口和一系列策略接口。Callback接口用于在持久对象的载入、存储、删除等事件发生时通知Hibernate。虽然Callback接口在用户程序中不是必需的,但在创建审计日志时可能会用到。而Hibernate的策略机制则赋予了它高度的可扩展性,这是与其他一些开源软件不同的地方。

Hibernate是一个功能强大、设计灵活的持久层框架,通过深入了解其各个接口和术语,我们可以更好地利用它构建高效、优雅的项目。Hibernate是一个强大的ORM框架,它允许开发者通过简单的Java代码与数据库进行交互。当Hibernate的某些默认功能无法满足我们的需求时,我们可以通过实现其提供的策略接口来扩展或替换其功能。Hibernate暴露了一系列策略接口,允许开发者根据自己的需求进行定制。

主键生成、本地SQL支持、缓冲机制、JDBC连接管理、事务管理、ORM策略、属性访问策略以及代理对象的创建等都是Hibernate的核心策略接口。只需要继承这些接口的默认实现,然后实现自己的逻辑,就可以轻松地扩展Hibernate的功能。

那么,开发者是如何获取Session的呢?Session是Hibernate中用于与数据库进行交互的主要接口。要获取Session,首先需要进行基础配置,创建一个SessionFactory对象。SessionFactory是线程安全的,只需要创建一次,然后在应用程序的生命周期中使用。

为了创建一个SessionFactory对象,需要创建一个Configuration类的实例,并处理映射文件。映射文件描述了Java类与数据库表之间的映射关系。将这些映射文件交给Configuration对象处理后,就可以创建一个SessionFactory对象。

在实际项目中,Hibernate可以在两种环境下运行:可管理环境和不可管理环境。可管理环境如J2EE服务器,提供了资源管理、事务管理和安全定义等功能。而不可管理的环境如servlet容器环境,只能提供一些基本的功能,事务处理、资源管理等都需要由应用程序自己定义。

对于开发者来说,大部分时间里都是在可管理的环境下工作。在这种情况下,Hibernate会将自己集成在J2EE环境中。创建SessionFactory的工作非常简单,只需从Configuration类创建一个实例,然后添加资源(映射文件)并设置属性即可。

映射文件的位置和命名都有特定的约定。默认情况下,映射文件以.hbm.xml为扩展名,并且每个持久类都应有一个独立的映射文件,以便于维护和管理。这些映射文件应放在classpath下的特定位置,以便Configuration类能够找到并处理它们。

Hibernate提供了丰富的策略和接口,允许开发者根据自己的需求进行定制和扩展。通过理解并善用这些策略和接口,开发者可以更加灵活地运用Hibernate,满足各种复杂的需求。Hibernate建议为每个持久类都创建一个与其同名的映射文件,并将其保存在与持久类相同的目录下。这样的组织方式清晰明了,就像在我们的示例程序中,Message持久类被放置在hello目录下,相应的映射文件也命名为Message.hbm.xml。这种结构避免了像struts项目中的“struts-config.xml地狱”这样的问题,使得管理更为简便。

如果你不遵循这一规则,你需要手动使用addResource()方法来加载每一个映射文件。如果你遵循这一建议,只需使用addClass()方法,就能轻松地将持久类和其映射文件一起载入。以下是一段示例代码:

SessionFactory sessions = new Configuration()

.addClass(hibernate.auction.model.Item.class)

.addClass(hibernate.auction.model.Category.class)

.addClass(hibernate.auction.model.Bid.class)

.setProperties(System.getProperties())

.buildSessionFactory();

Hibernate的映射文件具有许多其他配置选项,包括数据库连接的设定,以及能够改变Hibernate运行时行为的一些设定。尽管所有的设置可能看起来相当复杂,但你不必过于担心,因为Hibernate为大多数值都设定了合理的默认值,你只需要修改这些配置文件中的一小部分即可。

你可以通过以下几种方式来修改Hibernate的系统配置参数:

1. 创建一个Java.util.Properties实例并将其作为参数传递给Configuration类的setProperties()方法。

2. 在启动Hibernate时使用Java –Dproperty=value的方式设置值。

3. 在classpath可找到的路径下创建一个名为hibernate.properties的配置文件。

4. 在classpath可找到的路径下创建一个名为hibernate.cfg.xml的文件,并在其<property>标签中定义属性值。

以上就是关于Hibernate的大致介绍。如果你希望了解更多,现有的介绍还远远不够。我将陆续分享更多关于Hibernate的资料。但毫无疑问的是,它确实是一个出色的持久层解决方案!无论你是初学者还是经验丰富的开发者,Hibernate都能为你提供强大的功能和灵活的解决方案。

上一篇:PHP实现原生态图片上传封装类方法 下一篇:没有了

Copyright © 2016-2025 www.168986.cn 狼蚁网络 版权所有 Power by