第 2 章Hibernate入门.docx
- 文档编号:11547693
- 上传时间:2023-03-19
- 格式:DOCX
- 页数:21
- 大小:32.18KB
第 2 章Hibernate入门.docx
《第 2 章Hibernate入门.docx》由会员分享,可在线阅读,更多相关《第 2 章Hibernate入门.docx(21页珍藏版)》请在冰豆网上搜索。
第2章Hibernate入门
第 2 章 Hibernate入门
2.1. 前言
本章是面向Hibernate初学者的一个介绍教程。
我们将使用容易理解的方式,开发一个使用驻留内存式(in-memory)数据库的简单命令行程序。
本教程是面向Hibernate初学者,但是需要一定的Java和SQL知识。
它在MichaelGoegl所写的一个教程的基础上完成的。
我们使用的第三方库文件是支持JDK1.4和5.0。
如果你要使用JDK1.3,可能会需要其它的库。
2.2. 第一部分-第一个Hibernate程序
首先我们将创建一个简单的控制台(console-based)Hibernate程序。
我们使用内置数据库(in-memorydatabase)(HSQLDB),所以我们不必安装任何数据库服务器。
让我们假设我们希望有一个小程序可以保存我们希望关注的事件(Event)和这些事件的信息。
(译者注:
在本教程的后面部分,我们将直接使用Event而不是它的中文翻译“事件”,以免混淆。
)
我们做的第一件事是建立我们的开发目录,并把所有需要用到的Java库文件放进去。
从Hibernate网站的下载页面下载Hibernate分发版本。
解压缩包并把/lib下面的所有库文件放到我们新的开发目录下面的/lib目录下面。
看起来就像这样:
.
+lib
antlr.jar
cglib-full.jar
asm.jar
asm-attrs.jars
commons-collections.jar
commons-logging.jar
ehcache.jar
hibernate3.jar
jta.jar
dom4j.jar
log4j.jar
Thisistheminimumsetofrequiredlibraries(notethatwealsocopiedhibernate3.jar,themainarchive)forHibernate.SeetheREADME.txtfileinthelib/directoryoftheHibernatedistributionformoreinformationaboutrequiredandoptionalthird-partylibraries.(Actually,Log4jisnotrequiredbutpreferredbymanydevelopers.)这个是Hibernate运行所需要的最小库文件集合(注意我们也拷贝了Hibernate3.jar,这个是最重要的库)。
可以在Hibernate分发版本的lib/目录下查看README.txt,以获取更多关于所需和可选的第三方库文件信息(事实上,Log4j并不是必须的库文件但是许多开发者都喜欢用它)。
接下来我们创建一个类,用来代表那些我们希望储存在数据库里面的event.
2.2.1. 第一个class
我们的第一个持久化类是一个简单的JavaBeanclass,带有一些简单的属性(property)。
让我们来看一下代码:
importjava.util.Date;
publicclassEvent{
privateLongid;
privateStringtitle;
privateDatedate;
Event(){}
publicLonggetId(){
returnid;
}
privatevoidsetId(Longid){
this.id=id;
}
publicDategetDate(){
returndate;
}
publicvoidsetDate(Datedate){
this.date=date;
}
publicStringgetTitle(){
returntitle;
}
publicvoidsetTitle(Stringtitle){
this.title=title;
}
}
你可以看到这个class对属性(property)的存取方法(getterandsettermethod)使用标准的JavaBean命名约定,同时把内部字段(field)隐藏起来(privatevisibility)。
这个是个受推荐的设计方式,但并不是必须这样做。
Hibernate也可以直接访问这些字段(field),而使用访问方法(accessormethod)的好处是提供了程序重构的时候健壮性(robustness)。
id属性(property)为一个Event实例提供标识属性(identifierproperty)的值-如果我们希望使用Hibernate的所有特性,那么我们所有的持久性实体类(persistententityclass)(这里也包括一些次要依赖类)都需要一个标识属性(identifierproperty)。
而事实上,大多数应用程序(特别是web应用程序)都需要识别特定的对象,所以你应该考虑使用标识属性而不是把它当作一种限制。
然而,我们通常不会直接操作一个对象的标识符(identifier),因此标识符的setter方法应该被声明为私有的(private)。
这样当一个对象被保存的时候,只有Hibernate可以为它分配标识符。
你会发现Hibernate可以直接访问被声明为public,private和protected等不同级别访问控制的方法(accessormethod)和字段(field)。
所以选择哪种方式来访问属性是完全取决于你,你可以使你的选择与你的程序设计相吻合。
所有的持久类(persistentclasses)都要求有无参的构造器(no-argumentconstructor);因为Hibernate必须要使用Java反射机制(Reflection)来实例化对象。
构造器(constructor)的访问控制可以是私有的(private),然而当生成运行时代理(runtimeproxy)的时候将要求使用至少是package级别的访问控制,这样在没有字节码编入(bytecodeinstrumentation)的情况下,从持久化类里获取数据会更有效率一些。
我们把这个Java源代码文件放到我们的开发目录下面一个叫做src的目录里。
这个目录现在应该看起来像这样:
.
+lib
+src
Event.java
在下一步里,我们将把这个持久类(persistenclass)的信息通知Hibernate
2.2.2. 映射文件
Hibernate需要知道怎样去加载(load)和存储(store)我们的持久化类的对象。
这里正是Hibernate映射文件(mappingfile)发挥作用的地方。
映射文件告诉Hibernate它应该访问数据库里面的哪个表(table)和应该使用表里面的哪些字段(column)。
一个映射文件的基本结构看起来像这样:
xmlversion="1.0"?
>
DOCTYPEhibernate-mappingPUBLIC
"-//Hibernate/HibernateMappingDTD3.0//EN"
"
[...]
注意Hibernate的DTD是非常复杂的。
你可以在你的编辑器或者IDE里面使用它来自动提示并完成(auto-completion)那些用来映射的XML元素(element)和属性(attribute)。
你也可以用你的文本编辑器打开DTD-这是最简单的方式来浏览所有元素和参数,查看它们的缺省值以及它们的注释,以得到一个整体的概观。
同时也要注意Hibernate不会从web上面获取DTD文件,虽然XML里面的URL也许会建议它这样做,但是Hibernate会首先查看你的程序的classpath。
DTD文件被包括在hibernate3.jar,同时也在Hibernate分发版的src/路径下。
在以后的例子里面,我们将通过省略DTD的声明来缩短代码长度。
但是显然,在实际的程序中,DTD声明是必须的。
在两个hibernate-mapping标签(tag)中间,我们包含了一个class元素(element)。
所有的持久性实体类(persistententityclasses)(再次声明,这里也包括那些依赖类,就是那些次要的实体)都需要一个这样的映射,来映射到我们的SQLdatabase。
我们到现在为止做的一切是告诉Hibernate怎样从数据库表(table)EVENTS里持久化和加载Event类的对象,每个实例对应数据库里面的一行。
现在我们将继续讨论有关唯一标识属性(uniqueidentifierproperty)的映射。
另外,我们不希望去考虑怎样产生这个标识属性,我们将配置Hibernate的标识符生成策略(identifiergenerationstrategy)来产生代用主键。
id元素是标识属性(identiferproperty)的声明,name="id"声明了Java属性(property)的名字-Hibernate将使用getId()和setId()来访问它。
字段参数(columnattribute)则告诉Hibernate我们使用EVENTS表的哪个字段作为主键。
嵌套的generator元素指定了标识符的生成策略-在这里我们使用increment,这个是非常简单的在内存中直接生成数字的方法,多数用于测试(或教程)中。
Hibernate同时也支持使用数据库生成(databasegenerated),全局唯一性(globallyunique)和应用程序指定(applicationassigned)(或者你自己为任何已有策略所写的扩展)这些方式来生成标识符。
最后我们还必须在映射文件里面包括需要持久化属性的声明。
缺省的情况下,类里面的属性都被视为非持久化的:
和id元素类似,property元素的name参数告诉Hibernate使用哪个getter和setter方法。
为什么date属性的映射包括column参数,但是title却没有?
当没有设定column参数的时候,Hibernate缺省使用属性名作为字段(column)名。
对于title,这样工作得很好。
然而,date在多数的数据库里,是一个保留关键字,所以我们最好把它映射成另外一个名字。
下一件有趣的事情是title属性缺少一个type参数。
我们声明并使用在映射文件里面的type,并不像我们假想的那样,是Javadatatype,同时也不是SQLdatabasetype。
这些类型被称作Hibernatemappingtypes,它们把数据类型从Java转换到SQLdatatypes。
如果映射的参数没有设置的话,Hibernate也将尝试去确定正确的类型转换和它的映射类型。
在某些情况下这个自动检测(在Javaclass上使用反射机制)不会产生你所期待或者需要的缺省值。
这里有个例子是关于date属性。
Hibernate无法知道这个属性应该被映射成下面这些类型中的哪一个:
SQLdate,timestamp,time。
我们通过声明属性映射timestamp来表示我们希望保存所有的关于日期和时间的信息。
这个映射文件(mappingfile)应该被保存为Event.hbm.xml,和我们的EventJava源文件放在同一个目录下。
映射文件的名字可以是任意的,然而hbm.xml已经成为Hibernate开发者社区的习惯性约定。
现在目录应该看起来像这样:
.
+lib
+src
Event.java
Event.hbm.xml
我们继续进行Hibernate的主要配置。
2.2.3. Hibernate配置
我们现在已经有了一个持久化类和它的映射文件,是时候配置Hibernate了。
在我们做这个之前,我们需要一个数据库。
HSQLDB,一个java-based内嵌式SQL数据库(in-memorySQLDatabase),可以从HSQLDB的网站上下载。
实际上,你仅仅需要下载/lib/目录中的hsqldb.jar。
把这个文件放在开发文件夹的lib/目录里面。
在开发目录下面创建一个叫做data的目录-这个是HSQLDB存储它的数据文件的地方。
Hibernate是你的程序里连接数据库的那个应用层,所以它需要连接用的信息。
连接(connection)是通过一个也由我们配置的JDBC连接池(connectionpool)。
Hibernate的分发版里面包括了一些opensource的连接池,但是我们已经决定在这个教程里面使用内嵌式连接池。
如果你希望使用一个产品级的第三方连接池软件,你必须拷贝所需的库文件去你的classpath并使用不同的连接池设置。
为了配置Hibernate,我们可以使用一个简单的hibernate.properties文件,或者一个稍微复杂的hibernate.cfg.xml,甚至可以完全使用程序来配置Hibernate。
多数用户喜欢使用XML配置文件:
xmlversion='1.0'encoding='utf-8'?
>
DOCTYPEhibernate-configurationPUBLIC
"-//Hibernate/HibernateConfigurationDTD3.0//EN"
"
--Databaseconnectionsettings-->
hsqldb:
data/tutorial
--JDBCconnectionpool(usethebuilt-in)-->
--SQLdialect-->
--EchoallexecutedSQLtostdout-->
--Dropandre-createthedatabaseschemaonstartup-->
注意这个XML配置使用了一个不同的DTD。
我们配置Hibernate的SessionFactory-一个关联于特定数据库全局性的工厂(factory)。
如果你要使用多个数据库,通常应该在多个配置文件中使用多个
最开始的4个property元素包含必要的JDBC连接信息。
dialectproperty表明Hibernate应该产生针对特定数据库语法的SQL语句。
hbm2ddl.auto选项将自动生成数据库表定义(schema)-直接插入数据库中。
当然这个选项也可以被关闭(通过去除这个选项)或者通过Ant任务SchemaExport来把数据库表定义导入一个文件中进行优化。
最后,为持久化类加入映射文件。
把这个文件拷贝到源代码目录下面,这样它就位于classpath的root路径上。
Hibernate在启动时会自动在它的根目录开始寻找名为hibernate.cfg.xml的配置文件。
2.2.4. 用Ant编译
在这个教程里面,我们将用Ant来编译程序。
你必须先安装Ant-可以从Antdownloadpage下载它。
怎样安装Ant不是这个教程的内容,请参考Antmanual。
当你安装完了Ant,我们就可以开始创建编译脚本,它的文件名是build.xml,把它直接放在开发目录下面。
完善Ant
注意Ant的分发版通常功能都是不完整的(就像AntFAQ里面说得那样),所以你常常不得不需要自己动手来完善Ant。
例如:
如果你希望在你的build文件里面使用JUnit功能。
为了让JUnit任务被激活(这个教程里面我们并不需要这个任务),你必须拷贝junit.jar到ANT_HOME/lib目录下或者删除ANT_HOME/lib/ant-junit.jar这个插件。
一个基本的build文件看起来像这样
destdir="${targetdir}" classpathref="libraries"/> 这个将告诉Ant把所有在lib目录下以.jar结尾的文件加入classpath中用来进行编译。 它也将把所有的非Java源代码文件,例如配置和Hibernate映射文件,拷贝到目标目录下。 如果你现在运行Ant,你将得到以下输出: C: \hibernateTutorial\>ant Buildfile: build.xml copy-resources: [copy]Copying2filestoC: \hibernateTutorial\bin compile: [javac]Compiling1sourcefiletoC: \hibernateTutorial\bin BUILDSUCCESSFUL Totaltime: 1second 2.2.5. 安装和帮助 是时候来加载和储存一些Event对象了,但是首先我们不得不完成一些基础的代码。 我们必须启动Hibernate。 这个启动过程包括创建一个全局性的SessoinFactory并把它储存在一个应用程序容易访问的地方。 SessionFactory可以创建并打开新的Session。 一个Session代表一个单线程的单元操作,SessionFactory则是一个线程安全的全局对象,只需要创建一次。 我们将创建一个HibernateUtil帮助类(helperclass)来负责启动Hibernate并使操作Session变得容易。 这个帮助类将使用被称为ThreadLocalSession的模式来保证当前的单元操作和当前线程相关联。 让我们来看一眼它的实现: importorg.hibernate.*; importorg.hibernate.cfg.*; publicclassHibernateUtil{ publicstaticfinalSessionFactorysessionFactory; static{ try{ //CreatetheSessionFactoryfromhibernate.cfg.xml sessionFactory=newConfiguration().configure().buildSessionFactory
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Hibernate入门 Hibernate 入门