您的位置:首页 > 其它

Hibernete基础教程读书笔记(3-1)

2009-03-29 12:13 633 查看
第3章 构建简单的应用程序
在本章中,你将学习构建并运行第1章中的示例所需的步骤。还要重新构建一个略微复杂的应用程序。本书中的所有代码都可以从Apress站点(www.apress.com)下载。
3.1 安装工具
表3-1本书中使用的工具
工具
版本
下载位置
Hibernate
3.2.0
http://hibernate.org
Hibernate Tools
3.1
http://hibernate.org
Ant
1.6.5
http://ant.apache.org
HSQLDB
1.8.0.2
http://hsqldb.org
3.1.1 Hibernate和Hibernate Tools
通过http://hibernate.org上左边的菜单链接Download可以找到Hibernate的最新版本。应该选择Hibernate core3.2.0版本或更高版本(默然说话:现在应该是3.3.x)。
同样应该选择下载Hibernate Tools 3.1及以上版本。它为Ant构建工具和免费的Eclipse IDE提供了各种插件。在附录B中我们将讨论Eclipse特性。
3.1.2 HSQLDB 1.8.0
这个数据库是用Java编写的,而且是可以免费获得的开放源代码软件。我们的示例使用1.8.0.2版本,更高版本也适用。HSQL原来称为“Hypersonic”。在一些HSQL文档中可能会看到这个词,应该把它看作“HSQL”的同义词。Hibernate Query Language的缩写HQL与HSQL太相似,所以为了避免混淆,我们将HSQL称为HSQLDB。
如果你希望自己的数据库运行示例,那么应该处理以下方面的差异:
v Hibernate方法类
v JDBC驱动程序
v 数据库的连接URL
v 数据库的用户名
v 数据库的密码
在本章后面会介绍在哪里进行这些设置。你还会注意到,在指定数据库连接URL的地方,我们常会附加一个shutdown=true属性。这是为了纠正一个小问题:在Connection对象关闭前,HSQLDB并不将修改写到磁盘(当连接由Hibernate自己的连接池逻辑管理时,不会发生这种情况)。在非嵌入式数据库中,不需要这么做。
3.1.3 Ant 1.6.5
如果你不熟悉Ant,那么需要专门研究一下Ant这个主题。我们推荐Christopher M. Judd和Brian Sam-Bodden撰写的《Enterprise Java Development on a Budget》(Apress 2004年),这本书对Ant等开放源码工具做了很好的介绍。
尽管对Ant的详细讨论超出了本书的范围,但是我们将讨论脚本使用的Hibernate任务。
代码清单3-1给出构建本章示例所用的Ant脚本-build.xml
<?xml version="1.0" encoding="UTF-8"?>

<project name="sample">
<project file="build.properties" />

<project name="src" location="src" />
<project name="bin" location="bin" />
<project name="sql" location="sql" />
<project name="hibernate.tools" value="${hibernate.tools.home}${hibernate.tools.path}" location="src" />
<path id="classpath.base">
<pathelement location="${src}" />
<pathelement location="${bin}" />
<pathelement location="${hibernate.home}/hibernate3.jar" />
<fileset dir="${hibernate.home}/lib" includes="**/*.jar" />
<pathelement location="${hsql.home}/lib/hsqldb.jar" />
</path>

<path id="classpath.tools">
<path refid="classpath.base" />
<pathelement location="${hibernate.tools}/hibernate-tools.jar" />
</path>

<taskdef name="htools" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="classpath.tools" />
<target name="exportDDL" depends="compile">
<htools destdir="${sql}" >
<classpath refid="classpath.tools" />
<configuration configurationfile="${src}/hibernate.cfg.xml" />
<hbm2ddl drop="true" outputfilename="sample.sql" />
</htools>
</target>

<target name="compile">
<javac srcdir="${src}" destdir="${bin}" classpathref="classpath.base" />
</target>

<target name="populateMessages" depends="compile">
<java classname="sample.PopulateMessages" classpathref="classpath.base" />
</target>

<target name="listMessages" depends="compile">
<java classname="sample.ListMessages" classpathref="classpath.base" />
</target>

<target name="createUsers" depends="compile">
<java classname="sample.CreateUser" classpathref="classpath.base" >
<arg value="dave" />
<arg value="dodgy" />
</java>
<java classname="sample.CreateUser" classpathref="classpath.base" >
<arg value="jeff" />
<arg value="jammy" />
</java>
</target>

<target name="createCategories" depends="compile">
<java classname="sample.CreateCategory" classpathref="classpath.base" >
<arg value="retro" />
</java>
<java classname="sample.CreateCategory" classpathref="classpath.base" >
<arg value="kitsch" />
</java>
</target>

<target name="postAdverts" depends="compile">
<java classname="sample.PostAdvert" classpathref="classpath.base" >
<arg value="dave" />
<arg value="retro" />
<arg value="Sinclair Spectrum for sale" />
<arg value="48k original box and packaging" />
</java>
<java classname="sample.PostAdvert" classpathref="classpath.base" >
<arg value="dave" />
<arg value="kitsch" />
<arg value="Commemorative Plates" />
<arg value="Kitten and puppies design" />
</java>
<java classname="sample.PostAdvert" classpathref="classpath.base" >
<arg value="jeff" />
<arg value="retro" />
<arg value="Atari 2600 wanted" />
<arg value="Must have original joysticks." />
</java>
<java classname="sample.PostAdvert" classpathref="classpath.base" >
<arg value="jeff" />
<arg value="kitsch" />
<arg value="Inflatable Sofa" />
<arg value="Leopard skin pattern. Nice." />
</java>
</target>

<target name="listAdverts" depends="compile">
<java classname="sample.ListAdverts" classpathref="classpath.base" />
</target>
</project>
第一行导入的属性文件提供了安装的库的路径,应该根据自己的情况调整它(见代码清单3-2)。
Hibernate Tools压缩文件会解压出两个目录(plugins和features)。我们创建一个父目录来包含这两个目录。在解压的目录中,JAR文件(hibernate-tools.jar)的路径依赖于Hibernate Tools的版本,所以我们添加了hibernate.tools.path属性,将构建脚本指向这个路径。
代码清单3-2配置Ant脚本的build.properties文件
#hibernate的安装路径
hibernate.home=../tools/hibernate-3.2.0

#hibernate-tools安装路径
hibernate.tools.home=../tools/hibernateTools

#hibernate.jar相对于hibernate-tools安装路径的路径
hibernate.tools.path=/plugins/org.hibernate.eclipse_3.2.2.Beta1/lib/tools

#HSQL DB的安装路径
hsql.home=../tools/hsqldb
除了配置设置之外,build.xml文件中唯一比较怪的地方是,一个与Hibernate相关的Ant任务的配置和使用。taskdef(见代码清单3-3)使用tools.jar文件中的类定义这个任务。
代码清单3-3
<taskdef name="htools" classname="org.hibernate.tool.ant.HibernateToolTask" classpathref="classpath.tools" />
这个任务提供了几个子任务,但是本章中只使用hbm2ddl子任务。这个子任务读取映射文件和配置文件,并且生成Data Definition Language(DDL-数据定义语言)脚本,这些脚本可以在数据库中创建一个适当的模式(默然说话:模式?!原文好象是schema。根据上下文的意思,应该是指“表”吧?“在数据库中创建一个适当的模式”意思就是“在数据库中创建一个适当的表”吧?专用术语?!还是翻译是个外行?!)来表示我们的实体。
表3-2给出我们的构建脚本假设的基本目录,这些目录相对于示例项目的根目录。
表3-2 项目目录
目录
内容
src
源代码和配置文件(不包括那些与构建直接相关的文件)
bin
编译的类文件
sql
生成的DDL脚本
项目的根目录包含构建脚本和构建配置文件;在运行exportDDL任务时,它还包含HSQL生成的数据库文件
(默然说话:说实话,这一块相当混乱,如果你是Java初学者,建议你还是先练熟main()方法,过上个两三年,再来玩儿吧,要不,还是报个培训班,这样可以有教师指导你,虽然多花点钱,但进步会更快些。)
3.1.4 Ant任务
表3-3给出Ant构建脚本中包含的任务。
表3-3 Ant示例脚本中的任务
目录
内容
exportDDL
创建适当的数据库对象。它还生成一个脚本:如果需要的话,可以在HSQL数据库中运行这个脚本来重新创建这些对象。
compile
构建类文件。除了exportDDL(这个任务不需要类文件)之外的所有任务都依赖于这个任务,所以不需要直接调用它
populateMessages
用一个示例消息填充数据库
listMessages
列出由populateMessages存储在数据库中的所有消息
createUsers
在数据库中为Advert示例创建两个用户
createCategories
在数据库中为Advert示例创建两个产品目录
postAdverts
在数据库中为Advert示例创建几个广告
listAdverts
列出数据库中用于Advert示例的广告
3.1.5 启用日志记录
在运行本章中的任何示例之前,需要在类路径中创建一个log4j.properties文件。Hibernate Tools在解压的存档的etc目录中提供了一个示例。
我们的示例将这个文件放在项目的src目录中,而这个目录本身放在类路径中。在某些情况下(比如,在构建供其他项目使用的JAR文件时),将适当的属性文件和类文件一起复制到目标目录,可能是更好的方法。
(默然说话:这里我给大家一个示例好了)
代码清单m-1 log4j.properties文件的内容
log4j.rootCategory=WARN, console
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
log4j.appender.stdout.Target=System.out
3.2 创建Hibernate配置文件
Hibernate可以通过几种方式获得连接数据库和决定映射所需的所有信息。对于我们的Message示例,我们使用配置文件hibernate.cfg.xml,这个文件放在项目的src目录中,其内容见代码清单3-4.(默然说话:清单3-4的代码有错,少了DOCTYPE声明和根标签<hibernate-configuration>的开始。)
代码清单3-4 Message应用程序的配置文件:hibernate.cfg.xml
<?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">

<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.url">
jdbc:hsqldb:file:testdb;shutdown=true
</property>
<property name="hibernate.connection.driver_class">
org.hsqldb.jdbcDriver
</property>
<property name="hibernate.conncetion.username">sa</property>
<property name="hibernate.conncetion.password"></property>
<property name="hibernate.conncetion.pool_size">0</property>
<property name="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</property>
<property name="hibernate.show_sql">false</property>

<!--导入映射文件-->
<mapping resource="sample/entity/Message.hbm.xml" />
</session-factory>
</hibernate-configuration>
除了建立JDBC连接之外,各种与数据库相关的字段(hibernate.connection.*)应该看起来非常相似;但是hibernate.connection.pool_size属性例外,这个属性用来连接池特性,在使用HSQL数据库时这个属性会造成问题。show_sql值(在我们的示例中,设置为false)在调试程序的问题时极其有用――如果将它设置为true,那么Hibernate所准备的所有SQL就会输出到标准输出流(即控制台)。
我们还必须要为Hibernate选择将使用的方言,即使它是GenericDialect(详见第2章的讨论)。如果你真的选择GenericDilect,那么Hibernate就只能使用通用的SQL子集执行它的操作,而不能利用各种数据库特有的特性来提高性能。

注意 Hibernate会在类路径中寻找配置文件。如果将它放在其他地方,Hibernate就会认为你没有提供必要的配置信息。

Hibernate并不强制使用XML配置文件。你有两个选择。首先,可以提供一个普通的Java属性文件。与代码清单3-4等效的属性文件如下:
hibernate.connection.driver_class=org.hqldb.jdbcDriver
hibernate.connection.url=jdbc:hsqldb:file:testdb;shutdown=true
hibernate.connection.username=sa
hibernate.connection.password=
hibernate.show_sql=false
hibernate.dialect=org.hibernate.dialect.HSQLDialect
一件比较遗憾的事情是,你不能在属性文件中包含映射文件的信息。所以,如果你使用属性文件,那你只能通过在运行时将你的类直接映射到Hibernate的Configuration。实现这一目的的代码如下:
Configuration config=new Configuration();
config.addClass(sample.entity.Message.class);
config.setProperties(System.getProperties())
SessionFactory sessions=config.buildSessionFactory();
注意,Configuration对象会在类路径中寻找映射文件,映射文件应该在传递给Configuration对象的类的包中。在这个示例中,完全限定的类名是sample.entity.Message,应该能够从类路径的根目录找到以下两个文件:
/sample/entity/Message.class
/sample/entity/Message.hbm.xml
如果出于某种原因,你希望将映射文件放在另一个目录中,那么可以以资源的形式提供它们(注意,资源路径仍然必须相对于类路径),如下所示:
Configuration config=new Configuration();
config.addResource(“Message.hbm.xml”);
config.setProperties(System.getProperties());
SessionFactory session=config.buildSessionFactory();
可以使用任意数量的映射文件,只要给它们起不同的名字就行――简便的做法是为要映射的每个类创建一个映射文件,将它们放在类本身所在的目录,而且起相似的名称(例如,默认包中的Messag.hbm.xml对同在默认包中的Message类进行映射)。这样就可以迅速地找到与任何类对应的映射文件,所以映射文件的管理就很简便了。
对于大多数情况,我们认为XML配置文件是最合适的方法。
3.3 运行Message示例
安装了Hibernate和数据库,并且创建了配置文件之后,需要做的就是创建完整类,然后构建并运行。代码清单3-5到代码清单3-7中给出完整的代码:
代码清单3-5 Message POJO类
package com.speakermore.beginhb.ch03.entity;

public class Message {
private String message;
public Message(){}
public Message(String message){
this.message=message;
}
public String getMessage() {
return message;
}

public void setMessage(String message) {
this.message = message;
}
}
代码清单3-6是一个简单的应用程序,它用示例消息填充消息表。
代码清单3-6 创建示例消息的代码(测试代码)
package com.speakermore.beginhb.ch03.src;

import com.speakermore.beginhb.ch03.entity.Message;
import java.util.Date;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class PopulateMessages {
public static void main(String[] args) {
SessionFactory factory=new Configuration().configure().buildSessionFactory();
Session session=factory.openSession();
session.beginTransaction();

Message m1=new Message("在"+new Date()+"持久化了一个消息");

session.save(m1);
session.getTransaction().commit();
session.close();
}
}
最后,代码清单3-7给出另一个应用程序的完整代码,这个程序列出数据库中的所有消息。
代码清单3-7 消息应用程序
package com.speakermore.beginhb.ch03.src;

import com.speakermore.beginhb.ch03.entity.Message;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ListMessages {
public static void main(String[] args) {
SessionFactory factory=new Configuration().configure().buildSessionFactory();
Session session=factory.openSession();

List messages=session.createQuery("from Message").list();
System.out.println("找到"+messages.size()+"条消息");

for(Iterator i=messages.iterator();i.hasNext();){
Message msg=(Message)i.next();
System.out.println(msg.getMessage());
}
session.close();
}
}
Ant目标exportDDL会在HSQLDB数据库文件中创建一个适当的模式(默然说话:又是“模式”。。。请大家按“表”来理解。)运行populateMessages任务会创建一个消息记录(可以多次调用这个任务)。运行listMessages任务会列出到目前为止已经输入数据库中的消息。

注意:因为我们为exportDDL目标的hbm2ddl子任务选择了drop=”true”选项,所以运行这个脚本实际上会删除指定表中的所有数据。在能够对生产环境进行数据库访问的机器上,这通常是很危险的做法,因为有可能意外删除生产数据!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: