前言
Hibernate做为一个非常优秀且已经被大量使用的数据库持久层工具已经越来越成熟了。 本文主要是针对使用Hibernate的开发者,本章节主要是说明在《Hibernate开发指南》中所使用到的开发环境的初步设置, 并使用一个简单的例子以说明Hibernate已经正常运行。
本文所主要使用的工具有:
- JDK:JDK 1.4.2
- 开发集成环境:Eclipse 2.1.2
- Hibernate 2.1
- 数据库:Oracle 9i
- Hibernate的Eclipse插件:Tanghan Plugin
- Web应用服务器:Tomcat 4.x
- Struts 1.1包
- Eclipse的J2EE集成插件:MyEclipse 2.7RC1以上版本(2.7开始提供struts的支持)
软件配置
我们先来配置数据库,同时记下数据库开发时所需要的相关信息。
Oracle相关配置参数
我在Oracle中建立了一个单独的用户:HD,设置其密码为:abc。为该用户分配好相应的数据库空间, 细致的配置方法和信息不再多说,总之你需要得到类似下面的信息以备开发时所使用:
- 机器地址:hdibm(因为是在本机还可以使用localhost和127.0.0.1,如果是另一台机器使用该机器的IP地址)
- oracle的侦听端口:1521
- 数据库实例名:hdorc
- 访问用户名:hd
- 访问密码:abc
ojdbc14.jar
,JDK1.4使用的多语言支持包与JDK1.2相同都是
nls_charset12.jar
。
在数据库中我们建立一些表以用于程序开发,以一个简单的用户管理为例我们先建立一个简单的用户表(sysuser):
- 表名:sysuser
- 用户ID:userid(vchar:32)
- 用户名:username(vchar:20)
- 用户密码:userpasword(vchar:20)
- 用户最后登录时间:lastlogin(date)
CREATE TABLE "HD"."SYSUSER" ("USERID" VARCHAR2(32) NOT NULL, "USERNAME" VARCHAR2(20) NOT NULL, "USERPASWORD" VARCHAR2(20) NOT NULL, "LASTLOGIN" DATE, PRIMARY KEY("USERID"), UNIQUE("USERNAME")) TABLESPACE "USERS"
Tomcat安装
Tomcat的安装则非常简单了,从Tomcat网站上下载相关的安装包,解到相关的目录就可以了。安装Tomcat之后你需要记下以下信息:
- Tomcat的安装目录
- Tomcat的侦听端口(默认为8080)
配置Hibernate for Eclipse的插件Tanghan Plugin
初次使用这个插件时会有许多人无从下手,主要是不知从哪里使用这个插件。 首先要打开这个插件提供的两个视图:Database Access View
和Database Data View
。 通过菜单上的窗口>显示视图>其它来选择这两个视图:
打开Database Access View视图,我们来配置Oracle的驱动,用鼠标右键点Oracle Thin Driver>修改驱动程序信息:
这里:
- 驱动名称:Oracle Thin Driver
- 驱动程序包名:浏览选择你的ojdbc14.jar文件
- 驱动程序类:oracle.jdbc.driver.OracleDriver
- 驱动程序前缀:jdbc:oracle:thin:<username>@<password>//<server>[:<1521>]/<database_name>(这里是最新的驱动的URL书写方法,具体的最好看一下相关Oracle驱动的有关URL的说明)
这里:
- 数据库连接名:HDTestDB
- 驱动名称:Oracle Thin Driver(就是在上面我们建立的)
- 驱动程序类:oracle.jdbc.driver.OracleDriver
- 数据库连接:jdbc:oracle:thin:hd@abc//hdibm:1521/hdorc
- 用户名:hd
- 密码:abc
需要我们再选择Shemas,从下拉列表中选择HD
,按确定
按钮。 如果能看到选择Shemas对话框,哪么说明你的数据库配置就没有什么问题了。 我们可以在Database Access View中看到库中的表及表结构:
配置MyEclipse
从MyEclipse的网站上下载到最新的MyEclipse的试用版以及Struts相关的TLD和Lib包。 安装完MyEclipse后,配置Tomcat的使用。主要是配置清楚tomcat的相关路径就可以了:
需要注意的是tomcat一定要使用一个JDK,而不是JRE,在tomcat的配置树中可以选择一个JDK以供Tomcat启动使用:
接下来将从网站上下载的Struts包解开到文件系统中(也可以手工将Struts 1.1包中的lib和tld拆出),在MyEclipse中配置好Struts 1.1的相关包:
这些配置完成我们就可以建立一个简单的项目了。
建立初始的Struts项目
我们先建立一个项目,为后续的深入开发做准备,这个项目是一个简单的框架,导入Tomcat部署支持、建立与Struts和Hibernate的库路径。
为Web应用加入Struts支持
再为项目加入Struts支持:
在弹出的对话框中按下图输入信息:
这样就为Web应用项目加入了Struts支持,这一步会自动为项目加入Struts的支持包和Struts需要使用的TLD文件(Tag Lib说明文件)。之后我们可以看到:
为Web应用加入Hibernate支持
Hibernate中有大量的jar,不建议大家全部加入,以下是你必须加入的jar包(这些包除hibernate2.jar在根下其它都在lib子目录中):
- hibernate2.jar:Hibernate的核心库。
- cglib2.jar:Hibernate用来实现PO字节码的动态生成时所需要的库。
- commons-collections.jar:Apache Commons提供的比java.util.*功能更强的集合类。
- commons-lang.jar:Apache Commons提供了扩展java.lang.*的功能。
- commons-logging.jar:Apache Commons提供的一个通用日志接口工具。它会使用Log4j、JDK的java.util.logging、commons-logging的Simple Logger的顺序来寻找可用的log API。
- dom4j.jar:一个访问XML的java接口实现,Hibernate使用该包来完成XML的操作。
- odmg.jar:ODMG是一个ORM的规范,Hibernate使用这个包实现了ODMG规范。
- xalan.jar、xerces.jar和xml-apis.jar:XSLT处理器、SAX解析、标准JAXP API包,都是用于XML的处理。(大多应用服务器带有这三个包)
- c3p0.jar:C3PO数据库连接池所使用的包。
- commons-dbcp.jar和commons-pool.jar:Apache Commons提供的名为DBCP的数据库连接池所使用的包。
- jboss-cache.jar、concurrent.jar、jboss-common.jar、jboss-jmx.jar、jboss-system.jar:TreeCache所使用的包,它实现了一个可以集群的cache。
- connector.jar:标准JCA API包。大多应用服务器都带了。
- (*)ehcache.jar:EHCache cache包,Hibernate默认使用这个包来完成cache功能。
- jaas.jar:标准JAAS API包。大多应用服务器也带有这个包,这个包是供JCA来使用的。(JDK 1.4也已经包含这个包了)
- jcs.jar:JCS cache包。
- jdbc2_0-stdext.jar:标准JDBC 2.0 API扩展包。大多应用服务器也包含了这个包。
- swarmcache.jar和jgroups.jar:SwarmCache可复制的分布式Cache所使用的包。它使用JavaGroups进行组通讯,适合于集群环境的数据库应用Cache。
- (*)jta.jar:标准JTA API包。大多数应用服务器也带有这个包。
- log4j.jar:Log4包,Log4j是Logger工具中一个非常好的选择。
- oscache.jar:由OpenSymphony所提供的OSCache包,用于数据库的Cache。
- proxool.jar:Proxool JDBC数据库连接池包。
- ant.jar:编译Hibernat时使用的ant核心包。
- junit.jar:JUnit测试框架包,编译时为测试代码进行测试所使用的。
- optional.jar:Ant使用的辅助包,包括了一些附加的task。
下图是配置到最后所有的包的列表,也请大家一一核对:
配置Hibernate的配置文件
配置Hibernate数据库连接配置
数据库的连接配置很简单,在项目的src目录下建立一个xml文件,名为hibernate.cfg.xml。这个文件的内容为:
<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"> <hibernate-configuration> <session-factory> <property name="dialect">net.sf.hibernate.dialect.Oracle9Dialect</property> <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="connection.username">hd</property> <property name="connection.password">abc</property> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:hdorc</property> <property name="connection.pool.size">1</property> <property name="statement_cache.size">25</property> <property name="jdbc.fetch_size">50</property> <property name="jdbc.batch_size">30</property> <property name="show_sql">true</property> <!-- Mapping files --> <mapping resource="com/huangdong/demo/dao/SysUser.hbm.xml"/> </session-factory> </hibernate-configuration>
我们对这里的各个property元素一一说明:
- dialect:使用了Oracle9的对照
- connection.driver_class:Oracle的JDBC驱动类名
- connection.username:Oracle数据库访问用户名
- connection.password:Oracle数据库访问密码
- connection.url:Oracle数据库访问URL
- connection.pool.size:数据库连接池大小
- statement_cache.size:JDBC statement缓冲大小
- jdbc.fetch_size:设定JDBC的Statement读取数据的时候每次从数据库中取出的记录条数
- jdbc.batch_size:设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小
- show_sql:设定是否在控制台上显示向数据库提交的SQL语句,在开发调试时比较有用
配置Hibernate表映射
在Database Access View中选择SYSUSER表,在菜单中选择生成HBM文件:
在向导对话框中按下图输入相关信息:
按完成按钮后,就会在com.huangdong.demo.dao包中生成SysUser类和SysUser.hb.xml文件。
由于在Java中使用java.util.Date有很多不方便的地方,所以我将lastlogin的映射后的java属性改为了calendar。
这是修改后的SysUser.hbm.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="com.huangdong.demo.dao.SysUser" table="SYSUSER"> <id column="userid" length="32" name="userid" type="string"> <generator class="uuid.hex"/> </id> <property column="username" length="20" name="username" not-null="true" type="string" unique="true"/> <property column="userpasword" length="20" name="userpasword" not-null="true" type="string"/> <property column="lastlogin" length="7" name="lastlogin" type="calendar"/> </class> </hibernate-mapping>
这是修改后的SysUser.java文件:
package com.huangdong.demo.dao; import java.io.Serializable; import org.apache.commons.lang.builder.EqualsBuilder; import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.commons.lang.builder.ToStringBuilder; /** @author Hibernate CodeGenerator */ public class SysUser implements Serializable { /** identifier field */ private String userid; /** persistent field */ private String username; /** persistent field */ private String userpasword; /** nullable persistent field */ private java.util.Calendar lastlogin; /** full constructor */ public SysUser(java.lang.String username, java.lang.String userpasword, java.util.Calendar lastlogin) { this.username = username; this.userpasword = userpasword; this.lastlogin = lastlogin; } /** default constructor */ public SysUser() { } /** minimal constructor */ public SysUser(java.lang.String username, java.lang.String userpasword) { this.username = username; this.userpasword = userpasword; } public java.lang.String getUserid() { return this.userid; } public void setUserid(java.lang.String userid) { this.userid = userid; } public java.lang.String getUsername() { return this.username; } public void setUsername(java.lang.String username) { this.username = username; } public java.lang.String getUserpasword() { return this.userpasword; } public void setUserpasword(java.lang.String userpasword) { this.userpasword = userpasword; } public java.util.Calendar getLastlogin() { return this.lastlogin; } public void setLastlogin(java.util.Calendar lastlogin) { this.lastlogin = lastlogin; } public String toString() { return new ToStringBuilder(this) .append("userid", getUserid()) .toString(); } public boolean equals(Object other) { if ( !(other instanceof SysUser) ) return false; SysUser castOther = (SysUser) other; return new EqualsBuilder() .append(this.getUserid(), castOther.getUserid()) .isEquals(); } public int hashCode() { return new HashCodeBuilder() .append(getUserid()) .toHashCode(); } }
建立测试用的Servlet
创建Servlet框架
使用新建Servlet的向导我们来建立一个测试用的Servlet,下图是新建Servlet时输入的参数和选项:
在下一步的XML Wizard对话框中记得将Display Name和Description的“Test System Function Servlet”都清除,如下图所示:
这样就建立了一个初始的Servlet框架。
编写数据库连接获取类
我们编写一个单独的类,用于从SessionFactory中获取数据库连接session。这个类名为HibernateUtil,我们将其放于com.huangdong.demo.util包中,具体的代码如下:
package com.huangdong.demo.util; import net.sf.hibernate.HibernateException; import net.sf.hibernate.Session; import net.sf.hibernate.SessionFactory; import net.sf.hibernate.cfg.Configuration; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { sessionFactory = new Configuration().configure().buildSessionFactory(); } catch (HibernateException ex) { throw new RuntimeException( "Exception building SessionFactory: " + ex.getMessage(), ex); } } public static final ThreadLocal session = new ThreadLocal(); public static Session currentSession() throws HibernateException { Session s = (Session) session.get(); // Open a new Session, if this Thread has none yet if (s == null) { s = sessionFactory.openSession(); session.set(s); } return s; } public static void closeSession() throws HibernateException { Session s = (Session) session.get(); session.set(null); if (s != null) s.close(); } }
我们可以通过currentSession方法来获取数据库连接,如果系统中有可用的session就会反回可用的,如果没有时才会创建一个新的session。当session操作完成后,需要操作者使用closeSession方法释放使用的session。
建立测试Bean
接下来我们建立一个TestHibernate的Java Bean,主要加入一些Hibernate的测试方法,以下是建立该类所输入的相关信息:
我们为该类加入一个向数据库中增加数据的方法:
public boolean TestAdd() { try { Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); SysUser user = new SysUser(); user.setUsername("丫丫"); user.setUserpasword("uhkuhkqepdwqi"); user.setLastlogin(Calendar.getInstance()); session.save(user); tx.commit(); HibernateUtil.closeSession(); } catch (HibernateException e) { e.printStackTrace(); return false; } return true; }
第一次我写这个代码时感到非常的意外,总感觉应该再多写点什么,但是真的是这样,我们只用了这么几句话就向数据库加入了一条记录。
在Servlet中调用TestAdd方法
这就很简单了,更改TestServlet.java类的doGet方法,初始化TestHibernate类,并调用TestAdd方法就可以了:
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html; charset=GBK"); PrintWriter out = response.getWriter(); out.println( "<!DOCTYPE HTML PUBLIC /"-//W3C//DTD HTML 4.01 Transitional//EN/">"); out.println("<HTML>"); out.println(" <HEAD><TITLE>A Servlet</TITLE></HEAD>"); out.println(" <BODY>"); //调用Test Add TestHibernate test = new TestHibernate(); out.println("TestAdd:" + test.TestAdd() + "<p>"); out.println(" </BODY>"); out.println("</HTML>"); out.flush(); out.close(); }
如果TestAdd方法执行成功则会在页面上返回True,否则会返回False。下面我们就来测试一把。
测试我们第一个基于Servlet的Hibernate应用
启动Tomcat
如果之前按本文配置好了Tomcat的部署,哪么这里就不会有任何问题,如图操作则会进入Eclipse的调试视图:
在Debug视图中看到所有的线程启动,并在控制台窗口中看到“Starting Coyote HTTP/1.1 on port 8080”则说明Tomcat启动成功并侦听了8080端口,如下图:
打开浏览器,在地址栏中输入:
http://localhost:8080/Demo/servlet/TestServlet
如果返回的页面如下图所示,则代表数据库更新成功:
同时在Eclipse的控制台中我们可以看到Hibernate的log输出,说明了它工作的细节情况:
2003-12-26 15:10:37 net.sf.hibernate.cfg.Environment <clinit> 信息: Hibernate 2.1.1 2003-12-26 15:10:37 net.sf.hibernate.cfg.Environment <clinit> 信息: hibernate.properties not found 2003-12-26 15:10:37 net.sf.hibernate.cfg.Environment <clinit> 信息: using CGLIB reflection optimizer 2003-12-26 15:10:37 net.sf.hibernate.cfg.Configuration configure 信息: configuring from resource: /hibernate.cfg.xml 2003-12-26 15:10:37 net.sf.hibernate.cfg.Configuration getConfigurationInputStream 信息: Configuration resource: /hibernate.cfg.xml 2003-12-26 15:10:38 net.sf.hibernate.cfg.Configuration addResource 信息: Mapping resource: com/huangdong/demo/dao/SysUser.hbm.xml 2003-12-26 15:10:38 net.sf.hibernate.cfg.Binder bindRootClass 信息: Mapping class: com.huangdong.demo.dao.SysUser -> SYSUSER 2003-12-26 15:10:39 net.sf.hibernate.cfg.Configuration doConfigure 信息: Configured SessionFactory: null 2003-12-26 15:10:39 net.sf.hibernate.cfg.Configuration secondPassCompile 信息: processing one-to-many association mappings 2003-12-26 15:10:39 net.sf.hibernate.cfg.Configuration secondPassCompile 信息: processing one-to-one association property references 2003-12-26 15:10:39 net.sf.hibernate.cfg.Configuration secondPassCompile 信息: processing foreign key constraints 2003-12-26 15:10:39 net.sf.hibernate.dialect.Dialect <init> 信息: Using dialect: net.sf.hibernate.dialect.Oracle9Dialect 2003-12-26 15:10:39 net.sf.hibernate.cfg.SettingsFactory buildSettings 信息: JDBC result set fetch size: 50 2003-12-26 15:10:39 net.sf.hibernate.cfg.SettingsFactory buildSettings 信息: Use outer join fetching: true 2003-12-26 15:10:39 net.sf.hibernate.connection.DriverManagerConnectionProvider configure 信息: Using Hibernate built-in connection pool (not for production use!) 2003-12-26 15:10:39 net.sf.hibernate.connection.DriverManagerConnectionProvider configure 信息: Hibernate connection pool size: 20 2003-12-26 15:10:39 net.sf.hibernate.connection.DriverManagerConnectionProvider configure 信息: using driver: oracle.jdbc.driver.OracleDriver at URL: jdbc:oracle:thin:@localhost:1521:hdorc 2003-12-26 15:10:39 net.sf.hibernate.connection.DriverManagerConnectionProvider configure 信息: connection properties: {user=hd, password=abc, pool.size=1} 2003-12-26 15:10:39 net.sf.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup 信息: No TransactionManagerLookup configured (in JTA environment, use of process level read-write cache is not recommended) 2003-12-26 15:10:45 net.sf.hibernate.cfg.SettingsFactory buildSettings 信息: Use scrollable result sets: true 2003-12-26 15:10:45 net.sf.hibernate.cfg.SettingsFactory buildSettings 信息: JDBC 2 max batch size: 30 2003-12-26 15:10:45 net.sf.hibernate.cfg.SettingsFactory buildSettings 信息: echoing all SQL to stdout 2003-12-26 15:10:45 net.sf.hibernate.cfg.SettingsFactory buildSettings 信息: Query language substitutions: {} 2003-12-26 15:10:45 net.sf.hibernate.cfg.SettingsFactory buildSettings 信息: cache provider: net.sf.ehcache.hibernate.Provider 2003-12-26 15:10:45 net.sf.hibernate.cfg.Configuration configureCaches 信息: instantiating and configuring caches 2003-12-26 15:10:46 net.sf.hibernate.impl.SessionFactoryImpl <init> 信息: building session factory 2003-12-26 15:10:47 net.sf.hibernate.impl.SessionFactoryObjectFactory addInstance 信息: no JNDI name configured Hibernate: insert into SYSUSER (username, userpasword, lastlogin, userid) values (?, ?, ?, ?)
在最后我们可以看到Hibernate生成的数据库操作语句。走到这里可以说你已经成功的运行了许多东西。让我们再列出来,请你一一考虑一下它们是如何被你运行和部署起来的,它们有什么:
- Eclipse
- MyEclipse
- Tomcat
- Oracle/Oracle JDBC Driver
- Hibernate
- Struts(其实到现在我们还没有使用到它的功能)
留在最后的话
本文只是简单的给大家介绍了开发基于Java的Web应用的基础环境,同时介绍了一系列的开发工具和组件。 这些工具还有更多的功能,这里就不再一一介绍了,请大家多参考Eclipse、MyEclipse的说明文档,它们还有许多丰富的功能。 对于Struts和Hibernate这两个强大的组件最在后续的文章中再慢慢说明。
如果你对本文有什么意见和建议请联系我,告诉我你的想法,另外也可以到技术天空BBS的Java版中讨论与Java相关的各种技术。
你可以从这里下载到完整的Eclipse Project包。
另外本文中的所有代码在以下环境中由作者实际测试完全没有问题:
- Eclipse 2.1.2
- Struts 1.1
- Hibernate 2.1.1
- Tomcat 4.1.29/Jetty 4.2.15
- com.tanghan.plugin_0.1.0.12.21
- JDK 1.4.2_02 For Windows/FreeBSD 4.8/FreeBSD 4.9
- FreeBSD 4.8/FreeBSD 4.9/Windows 2000/Windows XP
- Oracle 9.2.0.1.0