目录
一、配置好Hibernate数据库连接
创建一个名为Hibernate的新工程,要使用Hibernate需要先创建一个数据库连接,选择Window工具栏Show View菜单中选择Other,在MyEclipse Enterprise Workbench目录下找到DB Browser数据库浏览器,先新建一个数据库连接驱动,输入正确的Connection URL数据库连接字符串和用户名密码,Add JARs选择本地的数据驱动文件,系统会自动选择驱动文件里的驱动类,完成之后在DB Browse里就多了一个数据库连接项,选择一个配置好的数据库连接项右击Open Connection连接,如果我们可以看到数据库和下面的表则证明配置数据库连接成功。右击工程项目选择MyEclipse菜单中的Add Hibernate Capabilities项,添加对Hibernate标签库的引用,选择Hibernate 3.1版,Next下一步使用hibernate.cfg.xml默认配置文件名,在连接数据库的步骤里我们选择JDBC驱动连接方式,在DB Driver下拉列表项中我们可以看到刚开始在DB Browser里配置好的数据库连接,选择一个下面的Connection URL数据库连接字符串和用户名密码自动填充,如果MyEclipse还未使用DB Browser数据库连接浏览器,我们可以先新建一个DB Browser数据库连接或直接在这一步骤手动输入数据库连接信息(建议先在DB Browser里配置一个数据库连接,因为后面实体映射也将要用到DB Browser),在Next下一步里选择创建一个SessionFactory类,输入Java package包名,如果没有预先创建好可以选择后面New新建一个,Finish完成之后项目就会添加Hibernate3.1 Core Libraries核心标签库,以及HibernateSessionFactory类和hibernate.cfg.xml数据库连接配置文件。
二、使用Hibernate映射数据库到实体类
配置好Hibernate的连接之后,我们需要对数据库表进行与实体映射,打开DB Browser数据库浏览器,找到要映射的表右击Hibernate Reverse Engineering,Hibernate会根据数据库表反向生成实体类,这里我们预先在数据库里创建一个FA_User表,SQL语句如下:
create table FA_User(
userid number not null,
username varchar2(20) not null,
password varchar(32) not null,
usernike varchar2(20),
regtime date not null,
constraint PK_FA_User primary key(userid)
);
在Hibernate Reverse Engineering映射选项里,先选择Java src folder添加到的包文件夹,勾选Hibernate mapping file(*.hbm.xml) for each database table,将产生一个实体映射到对应表的xml配置文件;勾选Java Data Object (POJO <> DB Table),将根据数据库表结构反向产生一个Java实体类,取消Create abstract class选项将不创建为抽象类,默认为implements实现java.io.Serializable可序列化的实体类,当然可为实体类指定Base persistent class基类;勾选Java Data Access Object (DAO),会创建实体类的数据访问类(DAO),这里我们勾选选择产生,Next下一步类可配置映射的一些选项,如在Customized Type Mappings里我们可以自定义数据库类型映射到实体的类型,这里我们按默认就好,Next下一步,选择表后在右边输入映射的Class name类和ID Generator主键生成类型,类名注意是要包括包的全名,主键类型则应该根据连接的数据库类定,如mysql为auto_increment自动增加主键类型应该选increment,sqlserver数据库自增则选择identity,这么我们使用oracle序列则选择sequence,大家也可以去研究其他类型的用法。下面Include referenced tables (A->B)和Include referenced tables (A<-B)可以包含A引用表和被引用表,在实体里面将创建各引用表的对应关系。完成之后工程将新加如下文件:
名称 | 描述 |
IBaseHibernateDAO | 数据库访问会话接口 |
BaseHibernateDAO | IBaseHibernateDAO接口实现类,数据访问基类 |
HibernateSessionFactory | 会话工厂实现类 |
UserDAO | User表数据访问类 |
User | User实体类 |
User.hbm.xml | User表映射对应关系配置文件 |
三、创建struts应用程序
上面配置好Hibernate数据访问框架后,我们来创建一个Struts简单应用程序使用Hibernate访问数据库,首先需要在工程里添加对Struts的引用,右击项目工程在菜单中选择MyEclipse项中的Add Struts Capabilities,选择Struts 1.2版本,修改Base package for new classes默认创建的action包名,点击完成添加对Struts标签库的使用。下面我们先完成一个简单的添加用户功能,先新建useradd.jsp页面,然后依次新建Struts From(UserFrom)和Struts Action(UserAction)。为了更好的配合Hibernate,在Struts From里直接使用Hebernate生成的实体类做为表单元素,同时便于维护,避免创建多个结构相同的表单,UserFrom代码如下:
package struts.form;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
public class UserForm extends ActionForm {
private hb.User user = new hb.User();
private List list;
public List getList() {
return list;
}
public void setList(List list) {
this.list = list;
}
public hb.User getUser() {
return user;
}
public void setUser(hb.User user) {
this.user = user;
}
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
// TODO Auto-generated method stub
return null;
}
public void reset(ActionMapping mapping, HttpServletRequest request) {
// TODO Auto-generated method stub
}
}
要注意上面的Struts Form使用的是user对象里面的字段,所以一定要默认初始化,不然将会出错。同时修改对应的useradd.jsp页面:
<pre style="color:red"><html:errors /></pre>
<html:form action="/user.do">
<p>
用户名:
<html:text property="user.username"></html:text>
</p>
<p>
密 码:
<html:password property="user.password"></html:password>
</p>
<p>
昵 称:
<html:text property="user.usernike"></html:text>
</p>
<p>
<html:submit value="提交"></html:submit>
</p>
</html:form>
注意上面property与实体属性的对应关系,在提交表单的时候,表单的值将填充到对应的property属性,在Struts Action里我们对输入的值进行一个简单的效验,execute方法如下:
UserForm userForm = (UserForm) form;
ActionMessages errors = new ActionMessages();
hb.UserDAO dao = new hb.UserDAO();
String username = userForm.getUser().getUsername(),password = userForm.getUser().getPassword();
if( username==null || username.trim().length()==0)
{
errors.add("username",new ActionMessage("用户名不能为空\n",false));
}
else if( dao.findByUsername(username).size() > 0)
{
errors.add("username",new ActionMessage("用户名已经存在\n",false));
}
if( password==null || password.length() == 0)
{
errors.add("password",new ActionMessage("密码不能为空\n",false));
}
if( errors.size() > 0 )
{
this.saveErrors(request,errors);
return mapping.getInputForward();
}
userForm.getUser().setRegtime(new java.util.Date());
dao.merge(userForm.getUser());
return new ActionRedirect("/index.jsp?msg=success");
编译重新运行,跳转提示保存成功,我们在来看下数据库,唉,数据库里没有记录,没有插入成功?这是因为Hibernate的默认merge方法里没有提交事务的原因,修改merge方法如下以进行提交。
public User merge(User user) {
Session session = getSession();
Transaction tr = session.beginTransaction();
try {
tr.begin();
User result = (User) session.merge(user);
tr.commit();
return result;
} catch (RuntimeException re) {
tr.rollback();
throw re;
}
}
当然我们也可以在hibernate.cfg.xml配置文件里进行全局设置,在session-factory节点下增加<property name="connection.autocommit">true</property>设置Hibernate默认提交事物,另外我们还需要注意Hibernate对象有三种状态,各种保存方法存在很大的区别,Eclipse自动生成的方法如下:
方法名 | 备注 |
save | 把一个新的对象保存 |
delete | 删除,持久化实例调用变成脱管状态 |
findById | 按ID查询数据 |
findByExample | 按传入实体对象所有字段值条件查询 |
findByProperty | 按某一字段属性值查 |
findAll | 返回所有 |
merge | 想当于save or update,并把一个游离态状态的对象转换为一个持久态对象,且返回这个对象 |
attachDirty | 将传入的对象持久化并保存 |
attachClean |
将传入的对象状态设置为Transient瞬态或者自由态 |
更多Hibernate对象状态和方法的详细介绍:http://www.blogjava.net/dreamstone/archive/2007/07/29/133071.html
更多Hibernate查询化语言HQL:http://blog.csdn.net/wllyy189/archive/2007/08/19/1750240.aspx
四、使用DispatchAction类执行不同方法
DispatchAction是继承自org.struts.action.Action的抽象类,它会根据request中的parameter来执行相应的方法,通个这个Action类可以将不同的Action集中到一个Action文件中来。还是以上面User为例,之前在UserAction的execute方法中实现了useradd添加用户功能,那我们现在继续在UserAction实现login用户登陆功能。首先需要修改struts-config.xml配置文件的Action的parameter为"action",那么在UserAction里将根据参数action执行方法,注意不要在UserAction里重写execute方法,不然不会执行对应的方法,unspecified是默认执行方法,另外所有执行方法的参数和返回类型必须和execute方法相同,UserAction代码如下:
public class UserAction extends org.apache.struts.actions.DispatchAction {
//默认执行方法
public ActionForward unspecified(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
try {
response.getOutputStream().print("unspecified default method");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//添加用户
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
UserForm userForm = (UserForm) form;
ActionMessages errors = new ActionMessages();
hb.UserDAO dao = new hb.UserDAO();
String username = userForm.getUser().getUsername(),password = userForm.getUser().getPassword();
if( username==null || username.trim().length()==0)
{
errors.add("username",new ActionMessage("用户名不能为空\n",false));
}
else if( dao.findByUsername(username).size() > 0)
{
errors.add("username",new ActionMessage("用户名已经存在\n",false));
}
if( password==null || password.length() == 0)
{
errors.add("password",new ActionMessage("密码不能为空\n",false));
}
if( errors.size() > 0 )
{
this.saveErrors(request,errors);
return new ActionForward("/useradd.jsp");
}
userForm.getUser().setRegtime(new java.util.Date());
dao.merge(userForm.getUser());
return new ActionRedirect("/index.jsp?msg=success");
}
//登陆
public ActionForward login(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
UserForm userForm = (UserForm) form;
ActionMessages errors = new ActionMessages();
hb.UserDAO dao = new hb.UserDAO();
String username = userForm.getUser().getUsername(),password = userForm.getUser().getPassword();
if( username==null || username.trim().length()==0)
{
errors.add("username",new ActionMessage("用户名不能为空\n",false));
}
else if( password==null || password.length() == 0)
{
errors.add("password",new ActionMessage("密码不能为空\n",false));
}
else if( dao.login(username, password)==null)
{
errors.add("username",new ActionMessage("用户名或密码错误\n",false));
}
if( errors.size() > 0 )
{
this.saveErrors(request,errors);
return new ActionForward("/login.jsp");
}
return new ActionRedirect("/index.jsp?msg=success");
}
}
那jsp页面action的提交地址也要相应的改变,通过/user.do?method=add传递parameter中参数调用相应的方法,struts-config.xml配置文件内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
<struts-config>
<data-sources />
<form-beans >
<form-bean name="userForm" type="struts.form.UserForm" />
</form-beans>
<global-exceptions />
<global-forwards >
<forward name="userlist" path="/index.jsp"></forward>
</global-forwards>
<action-mappings >
<action
parameter="action"
name="userForm"
path="/user"
scope="request"
type="struts.action.UserAction"
validate="false" />
</action-mappings>
<message-resources parameter="ApplicationResources" />
</struts-config>
Struts除此之外还有LookupDispatchAction、MappingDispatchAction两种类型的Action,这里简单的介绍下:LookupDispatchAction继承自DispatchAction,它的相应方法的执行由 ActionMapping中parameter属性决定。它适合在一个form中有很多按钮,按不同的按钮则执行不同的操作,同时在Action中必须实现getKeyMethodMap方法返回HashMap按钮和调用方法的键值对。MappingDispatchAction同样继承自DispatchAction,它的相应方法的执行由 ActionMapping中parameter名决定,注意这里和LookupDispatchAction不同,它是通过struts-config.xml将多个action-mapping映射到同一个Action类的不同方法上,也就是说在struts-config.xml配置多个Action指向同一个Action类但不同方法上。上面add和login这个方法的配置就应该为:
<action path="/user/add" parameter="add"
name="userForm" scope="request"
type="struts.action.UserAction" />
<action path="/user/login" parameter="login"
name="userForm" scope="request"
type="struts.action.UserAction" />
五、部署到Linux的Webligic应用服务器
以我公司的Redhat Linux AS4服务器为例,首先需要下载一个Weblogic安装程序,由于bea被oracle收购了,所以去oracle网站http://download.oracle.com/otn/linux/middleware/11g/wls/oepe11_ccjk_wls1031_linux32.bin下载一个linux版安装包,这里提醒大家不要去下载在线安装的,我因为用在线安装出错而重新安装了好几次,安装会默认装好JDK,这样我们创建一个weblogic的虚拟目录就能用了,weblogic安装完成后有一个http://localhost:7001/console的Web控制台,如果安装没有创建一个domain的话我们可以进那里创建一个。我的默认安装主目录是/root/Oracle/Middleware/,默认域网站目录为/root/Oracle/Middleware/user_projects/domains/base_domain/autodeploy,只要我们把打包好的网站上传到该目录即可,启动服务执行/root/Oracle/Middleware/user_projects/domains/base_domain/startWebLogic.sh。
由于使用的是Linux服务器,而开发我们是使用Windows系统,上传发布网站文件共享可使用Samba服务,Linux默认是关闭Samba服务的,使用service smb start命令可开启服务,下面在Linux下简单配置一个匿名用户可读可写的权限,vi /etc/samba/smb.conf修改smb配置文件内容如下:
[global]
workgroup = FA
netbios name = Linux
server string = Linux Samba Server
security = share
[weblogic]
path = /root/Oracle/Middleware
writeable = yes
browseable = yes
guest ok = yes
第二步,建立相应目录并授权,使用命令chown -R nobody:nobody /root/Oracle/Middleware为匿名用户和匿名用户组授权/root/Oracle/Middleware目录,service smb restart重起smb服务,windows下使用\\Linux就能访问到共享的Middleware目录,将部署好的Java工程项目拷贝到/root/Oracle/Middleware/user_projects/domains/base_domain/autodeploy目录下,使用http://192.168.0.249:7001/context就能访问到对应网站。这里要注意在weblogic中的路径问题,使用class.getClassLoader().getResource("").getPath()获取资源文件路径得到的不是WEB-INF/classes目录,而是webloic的lib主目录/root/Oracle/Middleware/wlserver_10.3/common/lib,而tomcat里正常。另外在weblogic里部署网站时候一些hibernate类文件也提示没有加载,后来在网站WEB-INF目录下增加weblogic.xml配置文件修改类的加载路径后解决。
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90">
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>UTF-8</java-charset-name>
</input-charset>
</charset-params>
<context-root>Hibernate</context-root>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>