• hibernate 结合servlet及 jsp 的使用


    Hibernate结合JSP使用

    前面几章详细的介绍了Hibernate的相关知识,这一章介绍Hibernate结合JSPServlet的使用,通过这一章的学习,可以加深对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;

    }

    //这里省略了settgetter方法

    }

    Dept类中有3个属性depnodepname对应数据库表的字段。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;

    }

    //这里省略了settergetter方法

    }

    用个实体类中有3个成员变量,empnoempname是数据库表这段对应的属性。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,代码如下(这里省略了htmlheadbody标签,用省略号代替)

    <%@ 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()方法,实现类EmpDaoImpqueryAllEmp()方法的代码如下:

    public List<Emp> queryAllEmp() {

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

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

    return list;

    }

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

    <%@ 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所示。

    Hibernate结合JSP使用<转载>

    14.1 添加员工页面

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

    Hibernate结合JSP使用<转载>

    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.jspshowEmpById.jsp页面的代码如下(这里省略了htmlheadbody标签,用省略号代替)

    <%@ 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表单提交到UpdateEmpServletUpdateEmpServlet是一个修改数据的ServletUpdateEmpServlet的代码如下(这里省略了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);//设置depnoDept的对象中

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

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

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

    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所示的页面。

    Hibernate结合JSP使用<转载>

    14.3 修改数据页面

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

    Hibernate结合JSP使用<转载>

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

    14.2.4 删除员工信息

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

    删除员工信息的Servlet——DeleteEmpById是处理删除信息的ServletDeleteEmpById的代码如下(这里省略了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所示。

    Hibernate结合JSP使用<转载>

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

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

    Hibernate结合JSP使用<转载>

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

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

    14.3 操作部门表

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

    14.3.1 添加部门信息

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

    <%@ 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是处理添加数据层的ServletAddDeptServlet的代码如下(这里省略了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);//调用实现类DeptDaoImpaddDept方法

    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();

    }

    }

    ShowAllDeptServletdoGet()方法中调用了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的代码如下(这里省略了htmlheadbody标签,用省略号代替):

    <%@ 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所示。

    Hibernate结合JSP使用<转载>

    14.7 添加部门信息页面

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

    Hibernate结合JSP使用<转载>

    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——DeleteDeptServletDeleteDeptServlet的代码如下(这里省略了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();

    }

    }

    DeleteDeptServletdoGet()方法中调用了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所示。

    Hibernate结合JSP使用<转载>

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

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

    Hibernate结合JSP使用<转载>

    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>();

    //调用EmpPageDAOImpgetAll方法获得查询结果

    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所示。

    Hibernate结合JSP使用<转载>

    14.11 分页显示的首页

    14.5 本章小结

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

    Top
    收藏
    关注
    评论
  • 相关阅读:
    数据结构与算法基础 模块七
    操作系统
    数据结构与算法基础 模块六
    数据库技术
    数据库技术
    数据库 SQL语句
    数据结构与算法基础 模块五
    同源策略和解决
    初识单例模式
    Django—内置用户权限管理
  • 原文地址:https://www.cnblogs.com/alanjl/p/3379476.html
Copyright © 2020-2023  润新知