在本教程中,您将使用 NetBeans IDE 创建和部署显示数据库中数据的 Web 应用程序。Web 应用程序将 Hibernate 框架用作持久性层,以便检索简单的传统 Java 对象 (Plain Old Java Object, POJO),并将其存储到关系数据库中。
Hibernate 是一个为对象关系映射 (ORM) 提供工具的框架。本教程介绍了如何向 IDE 添加对 Hibernate 框架的支持,以及如何创建所需的 Hibernate 文件。在创建 Java 对象并配置应用程序以使用 Hibernate 后,创建一个 JSF 受管 Bean 和 JSF 2.0 页面以显示数据。
在开始本教程之前,您可能需要熟悉以下文档。
目录
要学习本教程,您需要具备以下软件和资源。
软件或资源 | 要求的版本 |
---|---|
NetBeans IDE | 6.8 和 6.9,Java 版本 |
Java Development Kit (JDK) | 版本 6 |
GlassFish Server Open Source Edition | 3.0.1 |
MySQL 数据库服务器 | 版本 5.x |
Sakila 数据库 | 更新中心上可用的插件 |
注意:
您可以下载已完成项目的 zip 归档文件。
本教程使用一个名为 sakila 的 MySQL 数据库,这是一个免费的 MySQL 数据库,可从 MySQL 网站获得。安装 IDE 时并未包含 sakila 数据库,因此首先需要创建该数据库,以继续学习本教程。
要创建 sakila 数据库,可使用“插件”管理器下载并安装“Sakila 样例数据库”插件。安装该插件后,sakila 数据库即被添加到“创建 MySQL 数据库”对话框的数据库列表中。
有关配置 IDE 使用 MySQL 的更多信息,请参见连接 MySQL 数据库教程。
单击“确定”,“MySQL 服务器”节点下随即出现一个 Sakila 节点。
单击“连接”后,“数据库”节点下面将列出 Sakila 数据库连接节点 (jdbc:mysql://localhost:3306/sakila [username on Default])。打开连接时,可通过展开该连接节点查看数据库中数据。
在本练习中,您将创建一个 Web 应用程序项目并为该项目添加 Hibernate 库。创建该项目时,请在“新建项目”向导的“框架”面板中选择 Hibernate,并指定数据库。
(对于本教程,没有理由将项目库复制到指定文件夹,因为您将需要与其他用户共享库)。
注意: 如果向导的“框架”面板中没有 sakila 数据库这一选项,请查看该连接是否列示于“服务”窗口的“数据库”节点下。如果此处没有该连接,则需要创建数据库连接。
单击“完成”后,IDE 将创建 Web 应用程序项目,并在编辑器中打开 hibernate.cfg.xml 文件和 index.xhtml。
如果展开“项目”窗口中的“库”节点,则可以看到 IDE 已向项目中添加了 Hibernate 库。
创建使用 Hibernate 框架的新项目时,IDE 会自动在应用程序的上下文类路径的根路径(“文件”窗口中的 src/java)上创建 hibernate.cfg.xml 配置文件。该文件位于“项目”窗口的“源包”节点下的 <缺省包> 中。该配置文件包含有关数据库连接、资源映射和其他连接属性的信息。您可以使用多视图编辑器编辑该文件或直接在 XML 编辑器中编辑 XML。
在本练习中,您将编辑在 hibernate.cfg.xml 中指定的缺省属性,以启用 SQL 语句的调试日志记录以及 Hibernate 的会话上下文管理。
如果单击编辑器中的 "XML" 标签,则可以在 XML 视图中看到此文件。该文件应该如下所示:
<hibernate-configuration> <session-factory name="session1"> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/sakila</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">######</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.current_session_context_class">thread</property> </session-factory> </hibernate-configuration>
由于不需要再次编辑该文件,因此可以关闭该文件。
要使用 Hibernate,您需要创建一个 helper 类,该类处理启动并访问 Hibernate 的 SessionFactory 以获取“会话”对象。该类调用 configure() 并加载hibernate.cfg.xml 配置文件,然后构建 SessionFactory 以获取“会话”对象。
在此部分,使用“新建文件”向导创建 helper 类 HibernateUtil.java。
单击“完成”后,编辑器将打开 HibernateUtil.java。由于不需要编辑该文件,因此可以关闭该文件。
在本教程中,您将使用一个 POJO(简单传统 Java 对象)来表示您将要用到的数据库中的每个表中的数据。Java 类指定表的列字段,并使用简单的 setter 和 getter 方法检索数据和写数据。要将该 POJO 映射到表,可使用 Hibernate 映射文件或使用类标注。
您可以使用“通过数据库生成 Hibernate 映像文件和 POJO”向导根据数据库表创建多个 POJO 和映像文件。使用该向导时,选择希望从中创建 POJO 和映射文件的所有表,IDE 然后根据该数据库表生成文件并将映射条目添加到 hibernate.cfg.xml。使用向导时可选择希望 IDE 生成的文件(比如,只生成 POJO)并选择代码生成选项(比如,生成使用 EJB 3 标注的代码)
注意:IDE 还包含一些向导,以帮助您从头开始创建各个 POJO 和映射文件。
如果要使用“通过数据库生成 Hibernate 映射文件和 POJO”向导,您首先需要创建一个 hibernate.reveng.xml 逆向工程文件。“通过数据库生成 Hibernate 映射文件和 POJO”向导需要 hibernate.reveng.xml 和 hibernate.cfg.xml。
通过使用逆向工程文件,您可以更好地控制数据库映射策略。“Hibernate 逆向工程”向导创建一个具有缺省配置的逆向工程文件,可以在 XML 编辑器中编辑该文件。
要创建 Hibernate 逆向工程文件,请执行以下步骤。
单击“完成”。
该向导生成一个 hibernate.reveng.xml 逆向工程文件,并在编辑器中打开该文件。可将该逆向工程文件关闭,因为无需对其进行编辑。
有关使用 hibernate.reveng.xml 文件的详细信息,请参见以下指南中的第 5 章“控制逆向工程”:《Hibernate 工具参考指南》。
可以使用“通过数据库生成 Hibernate 映射文件和 POJO”向导来生成文件。该向导可以为您在向导中选择的每个表生成 POJO 和相应的映射文件。映射文件是 XML 文件,其中包含有关如何将表中的列映射到 POJO 中的字段的数据。您需要有 hibernate.reveng.xml 和 hibernate.cfg.xml 文件才能使用该向导。
要使用向导创建 POJO 和映射文件,请执行以下步骤。
单击“完成”后,IDE 生成 POJO 和 Hibernate 映射文件,并将字段映射到在 hibernate.reveng.xml 中指定的列。IDE 也添加映射条目到 hibernate.cfg.xml 中。展开 dvdrental 包查看由向导生成的文件。
如果要创建 Hibernate 映射文件以将特定表映射到特定类,您可以使用“Hibernate 映射”向导。
有关使用 hibernate.reveng.xml 文件的详细信息,请参见以下文档中的第 5 章“基本 O/R 映射”:《Hibernate 参考文档》。
现在,您将在 dvdrental 包中创建一个 helper 类,将用于在数据库中执行 Hibernate 查询。您将使用“Hibernate 查询语言(HQL)”编辑器来构造并测试用于检索数据的查询。测试了查询后,将在构造并运行查询的 helper 类中创建方法。然后,通过 JSF 受管 Bean 调用 helper 类中的方法。
在此部分,使用“新建文件”向导在 dvdrental 包中创建 helper 类 FilmHelper.java。您将通过调用 HibernateUtil.java 中的 getSessionFactory 来创建一个 Hibernate 会话,并创建一些 helper 方法以创建查询来检索数据库中的数据。将从 JSP 页面中调用这些 helper 方法。
public class FilmHelper { Session session = null; public FilmHelper() { this.session = HibernateUtil.getSessionFactory().getCurrentSession(); } }
现在将修改 FilmHelper.java 以添加查询数据库的方法。
在本练习中,将创建一个 Hibernate 查询语言 (HQL, Hibernate Query Language) 查询,以便查询数据库以从 Film 表中检索影片名称列表。然后,添加一个方法以查询 Actor 和 Film_actor 表,以便获取特定影片中涉及的演员。
Film 表包含 1000 条记录,因此检索影片列表的方法应该能够基于 filmId 主键检索记录。您将使用 HQL 编辑器构造和测试 HQL 查询。在创建正确的查询后,将在类中添加一个方法以生成相应的查询。
from Film
单击“运行 HQL 查询”可在 HQL 查询编辑器的 botton 窗口看到查询结果。
如果单击 SQL 按钮,可以看到起相同作用的 SQL 查询。
select film0_.film_id as col_0_0_ from sakila.film film0_
from Film as film where film.filmId between 100 and 200
结果窗口中显示了一个记录列表。测试过该查询可返回期待的结果后,可在 helper 类中使用该查询。
public List getFilmTitles(int startID, int endID) { List<Film> filmList = null; try { org.hibernate.Transaction tx = session.beginTransaction(); Query q = session.createQuery ("from Film as film where film.filmId between '"+startID+"' and '"+endID+"'"); filmList = (List<Film>) q.list(); } catch (Exception e) { e.printStackTrace(); } return filmList; }
public List getActorsByID(int filmId){ List<Actor> actorList = null; try { org.hibernate.Transaction tx = session.beginTransaction(); Query q = session.createQuery ("from Actor as actor where actor.actorId in (select filmActor.actor.actorId from FilmActor as filmActor where filmActor.film.filmId='" + filmId + "')"); actorList = (List<Actor>) q.list(); } catch (Exception e) { e.printStackTrace(); } return actorList; }
修复导入时,要选择 java.util.List 和 org.hibernate.Query.
现在将添加一些额外的 helper 方法,创建基于输入变量的查询。可在 HQL 查询编辑器中检查这些查询。
public Category getCategoryByID(int filmId){ List<Category> categoryList = null; try { org.hibernate.Transaction tx = session.beginTransaction(); Query q = session.createQuery("from Category as category where category.categoryId in (select filmCat.category.categoryId from FilmCategory as filmCat where filmCat.film.filmId='" + filmId + "')"); categoryList = (List<Category>) q.list(); } catch (Exception e) { e.printStackTrace(); } return categoryList.get(0); }
public Film getFilmByID(int filmId){ Film film = null; try { org.hibernate.Transaction tx = session.beginTransaction(); Query q = session.createQuery("from Film as film where film.filmId=" + filmId); film = (Film) q.uniqueResult(); } catch (Exception e) { e.printStackTrace(); } return film; }
public String getLangByID(int langId){ Language language = null; try { org.hibernate.Transaction tx = session.beginTransaction(); Query q = session.createQuery("from Language as lang where lang.languageId=" + langId); language = (Language) q.uniqueResult(); } catch (Exception e) { e.printStackTrace(); } return language.getName(); }