Hibernate结合JSP使用

前面几章详细的介绍了Hibernate的相关知识,这一章介绍Hibernate结合JSP和Servlet的使用,通过这一章的学习,可以加深对Hibernate的理解。

本章使用的开发工具是MyEclipse5.5,服务器是Tomcat6.0,数据库是MySQL5.1,本章所有例子源代码见光盘第14章的工程hibernate_jsp。

14.1 搭建Hibernate框架

使用Hibernate进行开发之前,需要先搭建Hibernate框架,Hibernate框架的搭建在前面已经介绍过。新建一个Web工程,工程名为hibernate_jsp。把连接MySQL数据库的jar包、Hibernate所需的jar包和JSTL标签库的jar包拷贝到该工程的WebRoot/WEB-INF/lib目录下。在MyEclipse中把工程hibernate_jsp发布到Tomcat服务器中。

14.1.1 创建数据库表

为了使例子简单易懂,创建数据库表时,表字段很少。本章的例子只需两张表,一张部门表和一张员工表。部门表的建表语句如下:

-- Table "dept" DDL

CREATE TABLE dept (

depno int(11) NOT NULL AUTO_INCREMENT,

depname varchar(255) DEFAULT NULL,

PRIMARY KEY (depno)

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=gb2312;

部门表的主键设置成自动增长。部门表和员工表是一对多的关系,所以在员工表中,部门表的主键作为员工表的外键,员工表的主键设置成自动增长。员工表的建表语句如下:

-- Table "emp" DDL

CREATE TABLE emp (

empno int(11) NOT NULL AUTO_INCREMENT,

empname varchar(255) DEFAULT NULL,

depno int(11) DEFAULT NULL,

PRIMARY KEY (empno),

KEY FK188C86CDD0E0B (depno),

CONSTRAINT FK188C86CDD0E0B FOREIGN KEY (depno) REFERENCES dept (depno)

) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=gb2312;

14.1.2 编写数据库表对应的实体类和映射文件

数据库表对应的实体类和实体类映射文件可以使用MyEclipse的向导来自动生成,也可以手动编写。这里使用MyEclipse的向导来自动生成。部门表对应的实体类Dept源代码如下:

package com.cn.vo;

public class Dept implements java.io.Serializable {

// Fields

private Integer depno;

private String depname;

private Set emps = new HashSet(0);//对应的员工实体类

// Constructors

public Dept() {

}

public Dept(Integer depno) {

this.depno = depno;

}

public Dept(Integer depno, String depname, Set emps) {

this.depno = depno;

this.depname = depname;

this.emps = emps;

}

//这里省略了sett和getter方法

}

Dept类中有3个属性depno和depname对应数据库表的字段。Set集合对应的是一对多的多方,这里是员工实体类。Dept类的对应的映射文件和实体类在同一包下,代码如下:

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!--

Mapping file autogenerated by MyEclipse Persistence Tools

-->

<hibernate-mapping>

<class name="com.cn.vo.Dept" table="dept" catalog="bank">

<id name="depno" type="java.lang.Integer">

<column name="depno" />

<generator class="native" />

</id>

<property name="depname" type="java.lang.String">

<column name="depname" />

</property>

<set name="emps" inverse="true">

<key>

<column name="depno" />

</key>

<one-to-many class="com.cn.vo.Emp" /><!-- 一对多关系映射 -->

</set>

</class>

</hibernate-mapping>

员工实体类是一对多关系中的多方,在员工表对应的实体类中要声明一方的对象(这里是Dept类对象),员工表对应的实体类Emp代码如下:

package com.cn.vo;

public class Emp implements java.io.Serializable {

// Fields

private Integer empno;

private Dept dept;//部门实体类对象

private String empname;

// Constructors

public Emp() {

}

public Emp(Integer empno) {

this.empno = empno;

}

public Emp(Integer empno, Dept dept, String empname) {

this.empno = empno;

this.dept = dept;

this.empname = empname;

}

//这里省略了setter和getter方法

}

用个实体类中有3个成员变量,empno和empname是数据库表这段对应的属性。Dept是员工表外键对应的属性,是一对多关系映射中的一方。Emp类对应的映射文件和实体类在同一包下,代码如下:

<?xml version="1.0" encoding="utf-8"?>

<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!--

Mapping file autogenerated by MyEclipse Persistence Tools

-->

<hibernate-mapping>

<class name="com.cn.vo.Emp" table="emp" catalog="bank">

<id name="empno" type="java.lang.Integer">

<column name="empno" />

<generator class="native" />

</id>

<!-- 多对一的关系映射 -->

<many-to-one name="dept" class="com.cn.vo.Dept" fetch="select">

<column name="depno" />

</many-to-one>

<property name="empname" type="java.lang.String">

<column name="empname" />

</property>

</class>

</hibernate-mapping>

14.1.3 编写Hibernate的配置文件

这个例子中使用XML文件来作为Hibernate的配置文件,文件名为hibernate.cfg.xml,在该文件中配置数据库连接和实体类映射文件,配置文件在src的跟目录下,代码如下:

<?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">

<!-- Generated by MyEclipse Hibernate Tools. -->

<hibernate-configuration>

<session-factory>

<!-- 连接数据库的配置 -->

<property name="connection.username">root</property>

<property name="connection.url">jdbc:mysql://localhost:3306/bank</property>

<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

<property name="myeclipse.connection.profile">com.mysql.jdbc.Driver</property>

<property name="connection.password">root</property>

<property name="connection.driver_class">com.mysql.jdbc.Driver</property>

<!-- 实体类的映射文件 -->

<mapping resource="com/cn/vo/Dept.hbm.xml"/>

<mapping resource="com/cn/vo/Emp.hbm.xml"/>

</session-factory>

</hibernate-configuration>

14.1.4 编写HibernateSessionFactory类

HibernateSessionFactory类是原来初始化Hibernate的,使用Hibernate开发时,必须编写该类。在类中编写如下代码(这里省略了import的内容):

package com.cn.factory;

public class HibernateSessionFactory {

private static Configuration cf = null;

private static SessionFactory sf = null;

static{

try {

cf = new Configuration().configure();

sf = cf.buildSessionFactory();//创建session

} catch (HibernateException e) {

throw new RuntimeException("SessionFactory创建失败",e);

}

}

public static Session getSession(){//获得session的方法

Session session = null;

try {

if (session==null||session.isOpen()==false)

session = null;

session = sf.openSession();

} catch (HibernateException e) {

throw new RuntimeException("Session创建失败",e);

}

return session;

}

public static void closed(Session session){//关闭session的方法

try {

if(session!=null)

session.close();

} catch (HibernateException e) {

throw new RuntimeException("Session关闭失败",e);

}

}

public static void main(String[] args) {//测试方法

getSession();

}

}

14.2 操作员工表

部门表的主键作为员工表的外键,所以在添加员工信息时,对应的部门信息要存在,否则抛出异常。这一节将介绍对员工表的增删改查操作。

14.2.1 添加员工信息

在添加员工信息之前,首先在MySQL的控制台中或者客户端工具中,往部门表中添加几条数据。添加员工信息的页面为addEmp.jsp,代码如下(这里省略了html、head和body标签,用省略号代替):

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

……

<form action="AddEmpServlet" method="post">

<table>

<tr>

<td>员工姓名</td>

<td><input type="text" name="ename"></td>

</tr>

<tr><td>部门编号</td>

<td><input type="text" name="depno"></td>

</tr>

</table>

<input type="submit" value="提交">

<input type="reset" value="重置">

</form>

……

上述代码中,from表单提交到AddEmpServlet中,使用post提交方式。页面中有连个文本框,员工编号是自动增长的,所以不用添加。AddEmpServlet的代码如下(这里省略了import的内容):

package com.cn.service;

public class AddEmpServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

String empname = request.getParameter("ename");//获得页面传递过来的数据

int depno = Integer.parseInt(request.getParameter("depno"));//获得页面传递过来的数据

Emp emp = new Emp();

Dept dept = new Dept();

dept.setDepno(depno);//把depno设置到dept对象中

emp.setEmpname(empname);//把empname设置到emp对象中

emp.setDept(dept);//把dept设置到emp对象中

EmpDao dao = new EmpDaoImp();

dao.addEmp(emp);//调用实现类的的添加方法

response.sendRedirect("ShowAllEmpServlet");//重定向到显示全部的Servlet中

out.flush();

out.close();

}

}

编写好Servlet以后,需要在WebRoot/WEB-INF/web.ml文件中配置Servlet信息。上述代码中有这样一行代码:

EmpDao dao = new EmpDaoImp();

其中EmpDao是一个接口,EmpDaoImp是接口实现类。这一行代码是接口实现类的对象指向接口的引用。接口类EmpDao中代码如下:

package com.cn.dao;

import java.util.List;

import com.cn.vo.Emp;

public interface EmpDao {

public void addEmp(Emp emp);//添加数据的方法

}

在接口实现类EmpDaoImp中实现addEmp方法。EmpDaoImp类的代码如下(这里省略了import的内容):

package com.cn.dao.imp;

public class EmpDaoImp implements EmpDao {

Session session = HibernateSessionFactory.getSession();//获得session

Transaction tr = session.beginTransaction();//开启事务

public void addEmp(Emp emp) {

session.save(emp);//添加数据

tr.commit();//提交事务

}

}

为了防止添加到数据库中的数据出现中文乱码,需要编写一个处理中文乱码的过滤器,过滤器的代码如下:

package com.cn.fileter;

import java.io.IOException;

import javax.servlet.*;

public class ChinaFilter implements Filter {

public void destroy() {

// TODO Auto-generated method stub

}

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

request.setCharacterEncoding("gb2312");//设置request的编码方式为gb2312

response.setCharacterEncoding("gb2312");//设置response的编码方式为gb2312

chain.doFilter(request, response);//提交处理

}

public void init(FilterConfig arg0) throws ServletException {

// TODO Auto-generated method stub

}

}

编写好这些代码以后,就可以正确的添加数据了。添加员工信息成功以后,页面跳转到ShowAllEmpServlet,所以添加数据的演示,放到显示全部员工信息部分一起演示。

14.2.2 显示全部员工信息

添加员工信息成功以后,页面跳转到ShowAllEmpServlet,该类是一个Servlet,用来显示全部员工信息,ShowAllEmpServlet的代码如下(这里省略了import的内容):

package com.cn.service;

public class ShowAllEmpServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

List<Emp> list = new ArrayList<Emp>();

EmpDao dao = new EmpDaoImp();

list = dao.queryAllEmp();//调用实现类的查询全部方法

request.setAttribute("list", list);//把查询结果放入request对象中

request.getRequestDispatcher("showAllEmp.jsp").forward(request, response);//转发到现实全部的页面

out.flush();

out.close();

}

}

上述代码中要在doGet方法中调用doPost方法,因为当页面跳转到Servlet中没有特别说明,会进入doGet方法中。在doPost方法中调用了接口实现类EmpDaoImp的查询全部方法queryAllEmp()方法。在接口EmpDao类中添加如下一行代码:

public List<Emp> queryAllEmp();//查询全部数据的方法

在接口实现类EmpDaoImp类中实现queryAllEmp()方法,实现类EmpDaoImp中queryAllEmp()方法的代码如下:

public List<Emp> queryAllEmp() {

List<Emp> list =session.createQuery("from Emp").list();//查询全部

tr.commit();//提交事务

return list;

}

在ShowAllEmpServlet中把查询到的全部数据放入List集合中,再把List集合对象放入request对象中。然后转发到显示全部员工信息的页面showAllEmp.jsp,showAllEmp.jsp页面的代码如下(这里省略了html、head和body标签,用省略号代替):

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

……

<table border="1">

<tr>

<td>员工编号</td>

<td>员工姓名</td>

<td>员工所在部门</td>

<td>操作</td>

</tr>

<c:forEach var="list" items="${list}">

<tr>

<td>${list.empno }</td>

<td>${list.empname }</td>

<td>${list.dept.depname }</td>

<td>

<a href="QueryEmpById?empno=${list.empno }">修改</a>

<a href="DeleteEmpById?empno=${list.empno }">删除</a>

</td>

</tr>

</c:forEach>

</table>

……

在MyEclipse中启动Toncat服务器,在IE浏览器的地址横纵中输入地址:“http://localhost:8080/hibernate_jsp/addEmp.jsp”,页面效果如图14.1所示。

图14.1 添加员工页面

在图14.1所示的页面中输入员工姓名和闭门编号以后,单击“提交”按钮,数据添加成功以后进入图14.2所示的页面。

图14.2 显示全部员工信息页面

在图14.2所示的页面中,显示了全部员工信息,同时提供了修改和删除的操作。接下来介绍修改和删除操作。

14.2.3 修改员工信息

修改数据的流程是:在页面通过超链接跳转显示单条数据信息的页面,在显示单条数据信息的页面中修改需要修改的数据,然后提交,把修改的数据提交到数据库中。然后再次跳转到显示全部员工信息的页面。

在图14.2所示的页面中,点击“修改”插连接时,传递员工编号参数进入根据编号查询的Servlet中(这里是QueryEmpById)。QueryEmpById的代码如下(这里省略import的内容):

package com.cn.service;

public class QueryEmpById extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

int empno = Integer.parseInt(request.getParameter("empno"));//获得页面传递的参数

Emp emp = new Emp();

EmpDao dao = new EmpDaoImp();

emp = dao.queryEmpById(empno);//调用实现类中根据id查询的方法

request.setAttribute("emp", emp);//把获得的对象放入request对象中

//转发到现实单条记录的页面

request.getRequestDispatcher("showEmpById.jsp").forward(request, response);

out.flush();

out.close();

}

}

上述代码中,在doGet()方法中调用doPost()方法,Servlet默认的进入的是doGet()方法,所以要在doGet()方法中调用doPost()方法。在doPost()方法中调用了实现类EmpDaoImp中的queryEmpById()方法。所以在接口EmpDao类中添加如下一行代码:

public Emp queryEmpById(int id);//根据id查询的方法

在实现类EmpDaoImp中要实现queryEmpById(int id)方法,所以在EmpDaoImp中编写queryEmpById(int id)方法,queryEmpById(int id)方法代码如下:

public Emp queryEmpById(int id) {

Emp emp = new Emp();

emp = (Emp) session.load(Emp.class, id);//根据id查询

return emp;

}

查询出数据以后,把数据放入request对象中,页面转发到显示单条记录的页面showEmpById.jsp。showEmpById.jsp页面的代码如下(这里省略了html、head和body标签,用省略号代替):

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

……

<form action="UpdateEmpServlet" method="post">

<table>

<tr>

<td>员工编号</td>

<td><input type="text" name="empno" value="${emp.empno }" readonly="readonly"></td>

</tr>

<tr>

<td>员工姓名</td>

<td><input type="text" name="ename" value="${emp.empname }"></td>

</tr>

<tr><td>部门编号</td>

<td><input type="text" name="depno" value="${emp.dept.depno }"></td>

</tr>

</table>

<input type="submit" value="提交">

<input type="reset" value="重置">

</form>

……

上述代码中,form表单提交到UpdateEmpServlet,UpdateEmpServlet是一个修改数据的Servlet。UpdateEmpServlet的代码如下(这里省略了import的内容):

package com.cn.service;

public class UpdateEmpServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

int empno = Integer.parseInt(request.getParameter("empno"));//获得页面传递过来的参数

String empname = request.getParameter("ename");//获得页面传递过来的参数

int depno = Integer.parseInt(request.getParameter("depno"));//获得页面传递过来的参数

Dept dept = new Dept();

Emp emp = new Emp();

dept.setDepno(depno);//设置depno到Dept的对象中

emp.setDept(dept);//设置dept到Emp对象中

emp.setEmpname(empname);//设置empname到Emp对象中

emp.setEmpno(empno);//设置empno到Emp对象中

EmpDao dao = new EmpDaoImp();

dao.updateEmp(emp);//调用实现类的修改方法

response.sendRedirect("ShowAllEmpServlet");//重定向到查询全部的Servlet

out.flush();

out.close();

}

}

该Servlet中的doGet方法调用doPost方法,修改的业务处理在doPost方法中处理。在doPost方法中,获得页面传递过来的数据以后,把数据设置到相应的对象中,调用了接口实现类EmpDaoImp中的修改方法。在接口EmpDao中添加修改方法updateEmp()方法,代码如下:

public void updateEmp(Emp emp);//修改数据的方法

在接口实现类EmpDaoImp中实现修改的方法,修改数据的方法updateEmp()方法的代码如下:

public void updateEmp(Emp emp) {

session.update(emp);//修改

tr.commit();//提交事务

}

要修改数据,需要在显示全部数据的页面中,点击修改超链接进入修改数据页面。启动Tomcat服务器,在IE浏览器地址栏中输入地址:“http://localhost:8080/hibernate_jsp/ShowAllEmpServlet”,在显示全部数据的页面中点击一个修改超链接,进入图14.3所示的页面。

图14.3 修改数据页面

在图14.3所示的页面中,员工编号是只读的,不能修改。员工姓名和闭门编号可以修改。输入修改后的数据,提交表单。修改成功后,页面跳转到图14.4所示的页面。

图14.4 修改成功后跳转到显示全部页面

14.2.4 删除员工信息

删除员工信息的可以通过在图14.4所示的页面中点击删除超链接,进入删除员工信息的Servlet,由Servlet调用删除的方法,实现删除员工信息的操作,删除成功后,页面跳转到显示全部员工信息的页面。

删除员工信息的Servlet——DeleteEmpById是处理删除信息的Servlet,DeleteEmpById的代码如下(这里省略了import的内容):

package com.cn.service;

public class DeleteEmpById extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

int empno = Integer.parseInt(request.getParameter("empno"));//获得页面传递的empno

EmpDao dao = new EmpDaoImp();

dao.deleteEmp(empno);//调用实现类中的查询方法

response.sendRedirect("ShowAllEmpServlet");//重定向到显示全部员工信息页面

out.flush();

out.close();

}

}

在DeleteEmpById类中的doGet方法中调用了doPost()方法,进入该Servlet时,默认进入的是doGet()方法,处理删除的过程在doPost()方法中实现,该方法中调用了接口实现类中的删除员工信息的方法,所以在接口EmpDao类中添加删除员工信息的方法deleteEmp()方法,代码如下:

public void deleteEmp(int id);//删除数据的方法

在接口实现类EmpDaoImp中要实现deleteEmp()方法,deleteEmp()方法的代码如下:

public void deleteEmp(int id) {

//使用Query对象来删除

Query query = (Query) session.createQuery("delete Emp where empno=:id");

query.setParameter("id", id);

query.executeUpdate();//删除

tr.commit();//提交事务

}

删除员工信息的代码都写好以后,可以在显示全部数据的页面中删除需要删除的员工信息,启动Tomcat服务器,在IE浏览器地址栏中输入地址:“http://localhost:8080/hibernate_jsp/ShowAllEmpServlet”,效果如图14.5所示。

图14.5 删除员工信息之前的页面

在图14.5所示的页面中删除应改变好为2的员工信息。员工编号为2的员工姓名是小张,所在部门是Java开发部。删除该条数据以后,进入图14.6所示的页面。

图14.6 删除员工信息以后的页面

在图14.6所示的页面中可以看到,员工编号为2的数据已经被删除了,这说明删除员工信息成功。这里的删除是单表删除,在下一节操作部门表中会讲到级联删除。

14.3 操作部门表

部门表的主键作为员工表的外键,所在在删除部门表信息的时候,需要级联删除员工表信息。本节中将介绍部门表信息的添加、查询和删除。修改操作和员工表的修改方法类似,这里就不再重复。

14.3.1 添加部门信息

添加部门信息时在页面中输入部门信息,提交表单后由后台处理添加业务。添加部门的页面addDept.jsp代码如下(这里省略了html、head和body标签,用省略号代替):

<%@ page language="java" pageEncoding="gb2312"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

……

<form action="AddDeptServlet" method="post">

<table>

<tr>

<td>部门名称</td>

<td><input name="deptName" type="text"></td>

</tr>

<tr>

<td><input type="submit" value="提交"></td>

<td><input type="reset" value="重置"></td>

</tr>

</table>

</form>

……

添加数据的表单提交到AddDeptServlet中,使用post方式提交表单内容。AddDeptServlet是处理添加数据层的Servlet,AddDeptServlet的代码如下(这里省略了import的内容):

package com.cn.service;

public class AddDeptServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

response.setCharacterEncoding("gb2312");//设置response编码方式

request.setCharacterEncoding("gb2312");//设置request编码方式

String depname = request.getParameter("deptName");//获得页面传递过来的数据

Dept dept = new Dept();

dept.setDepname(depname);//把获得的页面数据设置到Dept对象中

DeptDao deptDao = new DeptDaoImp();

deptDao.addDept(dept);//调用实现类DeptDaoImp的addDept方法

response.sendRedirect("ShowAllDeptServlet");//页面重定向到ShowAllDeptServlet中

out.flush();

out.close();

}

}

上述代码中,在doPost()方法中获得页面表单提交的数据,然后调用接口实现类DeptDaoImp中的addDept方法。首先编写接口DeptDao类,代码如下:

package com.cn.dao;

import java.util.List;

import com.cn.vo.Dept;

public interface DeptDao {

public void addDept(Dept dept);//添加部门

}

在接口实现类DeptDaoImp中实现addDept()方法,接口实现类DeptDaoImp的代码如下(这里省略了import的内容):

package com.cn.dao.imp;

public class DeptDaoImp implements DeptDao {

Session session = HibernateSessionFactory.getSession();//获得session

Transaction tr = session.beginTransaction();//开启事务

public void addDept(Dept dept) {

session.save(dept);//添加数据

tr.commit();//提交事务

}

}

在添加部门信息的Servlet中,添加数据成功以后,页面跳转到查询全部数据的Servlet中,所以添加数据的演示留到和查询全部数据一起演示。

14.3.2 查询全部部门信息

添加部门信息成功以后,页面跳转到查询全部部门信息的Servlet中,查询全部部门信息的Servlet——ShowAllDeptServlet的代码如下(这里省略了import的内容):

package com.cn.service;

public class ShowAllDeptServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

DeptDao dao = new DeptDaoImp();//接口实现类对象指向接口的引用

List<Dept> list =new ArrayList<Dept>();

list = dao.queryAllDept();//调用接口实现类中的queryAllDept方法

request.setAttribute("list", list);//把查询得到的集合放到request对象中

//转发到显示全部的页面中

request.getRequestDispatcher("showAllDept.jsp").forward(request, response);

out.flush();

out.close();

}

}

在ShowAllDeptServlet的doGet()方法中调用了doPost()方法,查询数据的操作的doPost()方法中处理。在doPost()方法中调用了接口实现类中的queryAllDept()方法。在接口DeptDao中添加queryAllDept()方法,代码如下:

public List<Dept> queryAllDept();//显示全部部门信息

在接口实现类DeptDaoImp中实现queryAllDept()方法,queryAllDept()方法代码如下:

public List<Dept> queryAllDept() {

//查询全部部门信息

List<Dept> list = session.createQuery("from Dept").list();

eturn list;

}

查询出全部的部门信息后,ShowAllDeptServlet转发到显示全部部门信息的页面showAllDept.jsp中,showAllDept.jsp的代码如下(这里省略了html、head和body标签,用省略号代替):

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

……

<table border="1">

<tr><td>部门号</td><td>部门名称</td><td>操作</td></tr>

<c:forEach var="list" items="${list}">

<tr>

<td>${list.depno }</td>

<td>${list.depname }</td>

<td>

<a href="DeleteDeptServlet?depno=${list.depno }">删除</a>

</td>

</tr>

</c:forEach>

</table>

……

现在来演示添加部门信息和查询全部部门信息。启动Tomcat服务器,在IE浏览器地址栏中输入地址:“http://localhost:8080/hibernate_jsp/addDept.jsp”,页面效果如图14.7所示。

图14.7 添加部门信息页面

在图14.7所示的页面中输入部门名称后,提交表单。添加部门信息成功后页面中显示出全部的部门信息,效果如图14.8所示。

图14.8 显示全部部门信息的页面

14.3.3 删除部门信息

部门表的主键是员工表的外键,在删除部门信息时,如果该条信息是员工表一些数据的外键时,需要把员工表的信息业删除掉。在编写删除操作之前,要在Dept.hbm.xml映射文件中设置一对多的级联操作,<set>中的代码修改成如下代码:

<set name="emps" inverse="true" lazy="false" cascade="all">

<key>

<column name="depno" />

</key>

<one-to-many class="com.cn.vo.Emp" />

</set>

在显示全部部门信息的页面中,点击删除超链接时,页面进入删除部门信息的Servlet——DeleteDeptServlet,DeleteDeptServlet的代码如下(这里省略了import的内容):

package com.cn.service;

public class DeleteDeptServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

int depno = Integer.parseInt(request.getParameter("depno"));//获得路径中的参数

DeptDao dao = new DeptDaoImp();

dao.deleteDept(depno);//调用删除方法

response.sendRedirect("ShowAllDeptServlet");//页面重定向到查询全部部门信息的Servlet

out.flush();

out.close();

}

}

在DeleteDeptServlet的doGet()方法中调用了doPost()方法,doPost()方法中获得路径中传递的参数,然后调用接口实现类DeptDaoImp中的deleteDept()方法。在接口DeptDao中添加deleteDept()方法,代码如下:

public void deleteDept(int id);//根据id删除数据

在接口实现类DeptDaoImp中要实现deleteDept()方法,deleteDept()方法代码如下:

public void deleteDept(int id) {

Dept dept = (Dept) session.load(Dept.class, id);

session.delete(dept);//删除数据

session.flush();

tr.commit();//提交事务

}

删除部门信息以后,该条信息对于的员工表外键数据也被删除,启动Tomcat服务器,在IE浏览器地址栏中输入地址:“http://localhost:8080/hibernate_jsp/ShowAllDeptServlet”,页面效果如图14.9所示。

图14.9 删除部门信息之前的页面

在图14.9所示的页面中删除掉部门编号为2的数据,该条数据对应的部门名称为市场部。删除成功后,页面进入图14.10所示的页面。

图14.10 删除部门信息成功以后的页面

再到数据中查询员工表的信息,发现外键为2的员工表信息都被删除了,这是因为在删除部门表信息时,使用了一对多的级联删除操作。

14.4 Hibernate的分页查询

当查询结果时很多数据时,一个页面无法全部显示出来,这个时候就用到了分页查询。Hibernate的页面查询方法是必须要掌握的一个知识点。这一节将介绍简单的Hibernate分页查询。为了便于理解,本节中的例子也采用分层来介绍,hql语句写在数据库访问层(即DAO层),Servlet中调用DAO层代码,在JSP页面中分页显示出来。

14.4.1 数据库访问层代码

数据库访问层也称DAO层,在DAO层中,要定义两个方法,一个方法是查询数据信息的方法,一个方法是求最大页数的方法。接口EmpPageDAO的代码如下:

package com.cn.page;

import java.util.List;

import com.cn.vo.Emp;

public interface EmpPageDAO {

public List<Emp> getAll(int pageNo, int pageSize);// 查询数据信息的方法

public int maxPage();//求最大页数的方法

}

在接口中定义的方法,要在接口实现类EmpPageDAOImp中实现这些方法,接口实现类EmpPageDAOImp的代码如下(这里省略了import的内容):

package com.cn.page;

public class EmpPageDAOImp implements EmpPageDAO{

Session session = HibernateSessionFactory.getSession(); //获得Session

public List<Emp> getAll(int pageNo, int pageSize) {

session.beginTransaction();

List<Emp> list = new ArrayList<Emp>();

//把查询结果放入list集合中,查询结果是根据页数来显示记录数

list = session.createQuery("from Emp")

.setFirstResult((pageNo-1)*pageSize)//每页显示的起始数据,pageNo表示页数

.setMaxResults(pageSize) //每页显示的末条数据,pageSize表示每页显示的数量

.list();

session.getTransaction().commit(); //提交事务

return list;

}

public int maxPage(){//求最大页数的方法

int count =0;//声明一个count变量,用于存储记录数

int maxpage = 0;//声明一个maxpage变量,原来表示最大页数

session.beginTransaction();

//获取总记录数

count = (Integer)session.createQuery("select count(*) from Emp").uniqueResult();

maxpage =(count+4)/5;// 这里的5是每页显示的条数,4是每页显示条数减1

return maxpage;

}

}

14.4.2 Servlet层的代码

在数据库访问层中声明了最大页数和查询数据信息的方法后,需要在Servlet中调用这些方法。这个例子中是在ShowEmpByPageServlet类中调用DAO层的方法,ShowEmpByPageServlet类的代码如下(这里省略了import的内容):

package com.cn.page;

public class ShowEmpByPageServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

this.doPost(request, response);//调用doPost方法

out.flush();

out.close();

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

response.setContentType("text/html");

PrintWriter out = response.getWriter();

String page = request.getParameter("page");//获得地址栏中传递的页数

int pageNo=1;//声明pageNo表示当前页数

int pageSize=5;//声明pageSize表示每页显示的数量

if(page!=null){//如果获得地址栏中的页数不为null。赋值给pageNo

pageNo = Integer.parseInt(page);

}

EmpPageDAO empPageDAOImp = new EmpPageDAOImp();

List<Emp> list = new ArrayList<Emp>();

//调用EmpPageDAOImp的getAll方法,获得查询结果

list = (List<Emp>) empPageDAOImp.getAll(pageNo, pageSize);

int maxPage = empPageDAOImp.maxPage();//获得最大页数

request.setAttribute("list", list);

request.setAttribute("page", pageNo);

request.setAttribute("maxpage", maxPage);

//转发到showEmpByPage.jsp页面

request.getRequestDispatcher("showEmpByPage.jsp").forward(request, response);

out.flush();

out.close();

}

}

在Servlet中调用接口实现类EmpPageDAOImp中的getAll()方法来获得查询信息,调用maxPage()方法来获得最大页数。把获得的当前页数、最大页数和查询结果放入request对象中,转发到JSP页面中。在JSP页面获得这些信息。

14.4.3 JSP页面分页

在JSP页面中获得Servlet转发过来的数据信息后,分页显示出获得的数据信息。在JSP页面中使用到JSTL标签库来遍历数据。分页显示的JSP页面——showEmpByPage.jsp代码如下:

<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head><title>My JSP 'showEmpByPage.jsp' starting page</title></head>

<body>

<table border="1" align="center">

<tr>

<td>员工编号</td>

<td>员工姓名</td>

<td>员工所在部门</td>

<td>操作</td>

</tr>

<c:forEach var="list" items="${list}">

<tr>

<td>${list.empno }</td>

<td>${list.empname }</td>

<td>${list.dept.depname }</td>

<td>

<a href="QueryEmpById?empno=${list.empno }">修改</a>

<a href="DeleteEmpById?empno=${list.empno }">删除</a>

</td>

</tr>

</c:forEach>

</table>

<div align="center">

<c:if test="${page ==1}">首页</c:if>

<c:if test="${page > 1}"><a href="/hibernate_jsp/ShowEmpByPageServlet?page=1">首页</a></c:if>

<c:if test="${page ==1}">上一页</c:if>

<c:if test="${page > 1}"><a href="/hibernate_jsp/ShowEmpByPageServlet?page=${page-1 }">上一页</a></c:if>

<c:if test="${page == maxpage}">下一页</c:if>

<c:if test="${page < maxpage}"><a href="/hibernate_jsp/ShowEmpByPageServlet?page=${page+1 }">下一页</a></c:if>

<c:if test="${page == maxpage}">末页</c:if>

<c:if test="${page < maxpage}"><a href="/hibernate_jsp/ShowEmpByPageServlet?page=${maxpage }">末页</a></c:if>

</div>

</body>

</html>

在showEmpByPage.jsp页面中,如果当前页面是第一页,则首页和上一页变成不可点击状态,如果当前页数是最大页,则下一页和末页变成不可点击状态。启动Tomcat服务器,在IE浏览器地址栏中输入地址:“http://localhost:8080/hibernate_jsp/ShowEmpByPageServlet”,页面效果如图14.11所示。

图14.11 分页显示的首页

14.5 本章小结

本章中使用Hibernate结合Servlet和JSP对数据库表数据进行了操作。操作员工表时,添加数据涉及到部门表的信息,所以在添加员工信息时,要确保外键存在。在操作部门表时,删除部门信息需要把员工表中有外键关联的数据删除,涉及到级联删除。本章好介绍了Hibernate的分页查询。

hibernate 结合servlet及 jsp 的使用的更多相关文章

  1. Spring,SpringMVC,MyBatis,Hibernate,Servlet的生命周期,jsp有哪些内置对象,Tomcat,Cookie和Session的作用以及区别,oracle,MYSQL等面试题总结

    1. 什么是Spring,谈谈你对Spring的理解 Spring是我们JAVA开发人员在搭建后台时选用的一个轻量级的开源框架,Spring框架目前也是功能丰富,十分优秀企业级采用最多的一个框架. S ...

  2. 基于Servlet、JSP、JDBC、MySQL的一个简单的用户注冊模块(附完整源代码)

    近期看老罗视频,做了一个简单的用户注冊系统.用户通过网页(JSP)输入用户名.真名和password,Servlet接收后通过JDBC将信息保存到MySQL中.尽管是个简单的不能再简单的东西,但麻雀虽 ...

  3. SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。

    熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...

  4. Servlet,jsp,JSP技术 ,JSP编程

     一.Servlet 思考 1 浏览器可以直接打开JAVA/class文件吗? 不可以 2浏览器可以打开HTML.JS 文件吗? 可以 3 JAVA程序可以生成HTML文件吗?可以的,用IO流. 4 ...

  5. Servlet与JSP版本历史以及Tomcat支持的版本

    查询这个的关键字:Java EE的版本历史. JavaServer Pages (JSP) Java Servlet 参考: https://en.wikipedia.org/wiki/Java_EE ...

  6. JBoss和Tomcat版本、及Servlet、JSP规范版本对应一览 【转】

    原文地址:http://blog.csdn.net/hills/article/details/40896357 JBoss和Tomcat版本.及Servlet.JSP规范版本对应一览 JBossAS ...

  7. 你也可以当面霸-Servlet与JSP的原理及特点

    既然是面试系列,就是面试官和应聘者之间的对话.本文是采用一问一答的形式呈现给读者的,这样能有一个明确的考察点,不像理论知识那么枯燥. 01.什么是Servlet技术 Servlet是和平台无关的服务器 ...

  8. Servlet、JSP选择题(2)

    Java EE软件工程师认证考试 试题库-选择题 一.    选择题(包括单选和双选) 1.B 编写一个Filter,需要(  ) A. 继承Filter 类 B. 实现Filter 接口 C. 继承 ...

  9. Servlet的生命周期,并说出Servlet和CGI的区别,Servlet与JSP的区别

    一.Servlet 生命周期 1.加载 2.实例化 3.初始化 4.处理请求 5.销毁 二.Servlet与cgi的区别: Servlet处于服务器进程中,它通过多线程方式运行其service方法,一 ...

随机推荐

  1. Metro应用Json数据处理

    Windows Phone 8 或者 Windows 8 平台对JSON数据的处理方式基本是一致的,需要使用DataContractJsonSerializer类将对象的实例序列化为JSON字符串,并 ...

  2. [ python ] 正则表达式及re模块

    正则表达式 正则表达式描述: 正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符.及这些特定字符的组合,组成一个‘规则字符串’,这个‘规则字符串’用来    表达对字符串的一种过滤 ...

  3. Codefroces 919D Substring(拓扑排序+DP)

    题目链接:http://codeforces.com/problemset/problem/919/D 题目大意:给你一张有向图,给你每个顶点上的字母和一些边,让你找出一条路径,路径上的相同字母数最多 ...

  4. MVC基础知识 – 2.新语法

    1.自动属性 Auto-Implemented Properties 2.隐式类型 var 3.参数默认值 和 命名参数 4.对象初始化器 与 集合初始化器 { } 5.匿名类 & 匿名方法 ...

  5. 如何修改WP文章字体格式、字号大小、字体颜色

    在使用wordpress编辑文章的时候,很多朋友会像小编一样,发现它并没有像word文档一样有修改字体样式.字体大小.字体颜色.分页符等功能按钮,对我们写文章极为不便,原因是wordpress默认使用 ...

  6. 关于Android不同系统版本的市场占比情况详解

    一,google官方统计的不同Android版本市场的占比强开 google统计的数据情况 这个是google官方对于不同版本的市场占比情况.这个是针对全世界所有的Android手机占比情况. 二,友 ...

  7. (转)粒子编辑器Particle designer属性的介绍

    转载:http://blog.csdn.net/ym19860303/article/details/9210539 Particle designer粒子编辑器可到这里下载(包含授权码):http: ...

  8. yii2 GirdView使用全教程

    开始GridView GridView主要是为了实现表格复用,尤其我们做后台的时候,你发现表单和表格占据了大部分页面,而表格的样式又是高度的统一,那么如果有这样一个挂件,传入数据集自动渲染表格该多好. ...

  9. JS获取select的value和text值的简单实例

    本篇文章主要是对JS获取select的value和text值的简单实例进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助 代码如下: <select id = "cityList ...

  10. RecyclerView悬浮标题

    效果图:        1.顶部会悬浮章的部分 2.第二章上滑会推挤第一章 3.第二章下拉会带出第一章 4.并不是所有时候都有悬浮部分(为什么这条标红,因为市面上几乎所有的悬浮都是必须存在且在顶部,害 ...