zoukankan      html  css  js  c++  java
  • Struts+Spring+Hibernate开发实例

    介绍

    本文并不想介绍StrutsSpringHibernate的原理系统架构等,本文地目的是通过一个较复杂地实例介绍如何整合StrutsSpringHibernate,网上现有的例子虽然也能达到目的,但功能都比较单一,复杂的例子时会有意想不到的麻烦。本文对读者假设已经具备了以上框架的基础知识。以及那些已经了解StrutsSpringHibernate的基本概念,但是还没有亲身在较复杂的项目中体验StrutsSpringHibernate的开发人员。

    1 Struts

        虽然不打算过多介绍Struts的原理,但是大概介绍一下还是有必要的。Struts本身就是 MVC 在这里负责将用户数据传人业务层,以及 将业务层处理的结果返回给用户,此系统属于较简单WEB应用,采用了OpenSessionInView模式处理LazyLoad问题,这样我们可以在用户视图中使用 getset方法来方便地获取关联对象。为了处理庞大的ActionActionForm问题,在此我门准备使用DynaActionForm (DynaValidatorForm)DispatchAction以及 动态验证框架 来解决。及使用Tile来解决框架问题 。使用自定义标签处理分页和身份验证问题。

    2 Spring

        Spring Framework最得以出名的是与Hibernate的无缝链接,虽然Spring Hibernate提供了90%以上的封装,使我们不必去关心Session 的建立,关闭,以及事务使我们能够专心的关注业务逻辑。但是一些特殊情况如 有时需要Query以及Criteria 对象,分页等,Spring不能给我们提供支持,总不能每次都在你的DAO上写个HibernateCallBackup()吧?Spring的作用不是把Hibernate再封装一层,而是让你接触不到HibernateAPI,而是帮助你管理好SessionTransaction

    在这里解决方法是:首先 写一个IBase 的接口,和一个BaseDao的实现。在实现中仿照HibernateTemplate,将其功能一一实现,同时考虑到Spring 未能支持的地方,我们不得已只好自己来管理Session,因此加入public Session openSession()public Query getQuery(String sql)public Criteria getCriteria(Class clazz),以及分页的方法。 然后为每一个Entity 都建立继承于以上类的IEntity,与EntityDao。这里可以根据需求对Entity加入特殊的方法实现,如 StudentsDao.java 中加入类似用户身份验证等。以上就是数据访问层。接下来在Service层中通过对dao的引用完成业务逻辑方法。在下面的例子中我们分别为学生模块,教师模块,管理员模块构建Service层,StudentsServiceImplTeachersServiceImplAdminServiceImpl

     

    3 Hibernate

     有了Spring的封装,我们要对Hibernate做的就是正确实现对象关系的映射。由于此处处于系统的最底层,准确无误的实现对象之间的关联关系映射将起着至关重要的作用。

     总之,理解了StrutsSpringHibernate地原理以及之间的关系之后,剩下的工作就如同在以Spring为核心的Struts为表现的框架中堆积木。

    下图可以更好的帮助我们理解StrutsSpringHibernate之间的关系。
    pic1.JPG

    案例简述

    设计思路主要源于 大学选修课,该系统可以方便处理学生在课程选报,学分查询,成绩查询,以及 成绩发布等。

    系统以班级为核心,一门课程可以对应多个班级,一名教师也可以带不同的班级,学生可以选报不同课程所对应的班级,班级自身有目前人数,和最大人数,以及上课时间,上课地点的属性。

    学生在选报班级之后,班级的人数会自动加一,直到等于最大人数时,其他学生将会有人数已满的错误提示。同理如果学生选择了同一课程的不同班级,也将收到错误提示。学生有密码,系别,学分,地址,电话等属性。

    教师在系统中主要负责成绩发布,教师可以对其所带的班级的学生的成绩修改,系统会以成绩是否大于等于60来判断学生是否通过考试,如果通过会将该课程的学分累加到学生学分,同样如果教师二次修改了成绩,而且小于60,系统会在学生学分上扣掉该课程的分数。

    课程在系统中具体体现为班级,自身带有学分属性。
    < body>

    系有编号,名称的属性,同时可以作为联系教师,课程,学生的桥梁。

     

    功能模块

    l       身份验证模块: 根据用户名,密码,用户类别 转发用户到不同的模块。

    l       学生模块: 查看课程,查看班级,选报课程,查看己选课程,成绩查询。

    l       教师模块: 录入成绩

    l       管理员模块:对学生,教师,课程,班级,系 增,删,查,改。

     

    具体实践

    代码下载
    http://www.blogjava.net/Files/limq/StudentManger.rar
    1  
    对象关系映射:

    首先,将库表映射为数据模型(SQL在源码中查看),转换后的数据模型如下图:
    pic2.jpg

    由此我们可以看出一下关联关系:

    1 Students Contact(联系方式)一对一关系。

    2 Students History(选课历史) 一对多关系

    3 Students Classes 多对多关系。

    4 Classes Classes_info 一对多关系。

    5 Classes Teachers 多对一关系。

    6 Classes Courses 多对一关系。

    7 Course Department(系) 多对一关系。

    8 Teachers Department 多对一关系。

    9 Students Department 多对一关系。

     

    Hibernate中将以上关系一一映射,如Students History 一对多关系

    Students.cfg.xm.

     1 <set name="history"
     2                  table="history" 
     3                  cascade="all"
     4                  inverse="true"
     5                  lazy="true"  >
     6                 <key  column="student_id"/> 
     7             <one-to-many class="limq.hibernate.vo.History"
     8                                     />
     9             set>
    10 

    同样在History.cfg.xml中加入:

    1  <many-to-one name="student"
    2                   class="limq.hibernate.vo.Students"
    3                   column="student_id"  >    
    4      many-to-one>
    5 

    用过MyEclipse开发Hibernate的就知道,MyEclipse会帮助我们生成持久对象和抽象对象,我们要在 Students.java 中加入对History的引用

    private Set history=new HashSet();

     

         public Set getHistory() {

            return history;

          }

     

        public void setHistory(Set history) {

            this.history = history;

    }

    同时,在AbstractHistory.java 中删除student_id 以及对应的getset 方法,History.java 中加入

    private Students student;

    public Students getStudent() {

            return student;

        }

      

     public void setStudent(Students student) {

            this.student = student;

        }

    具体内容请查看 源代码。

    2 DAO 数据访问层

    首先,编写IBaseDaoBaseDao,其中IBaseDao代码如下:

     1 package limq.hibernate.dao;
     2 
     3 import java.util.Collection;
     4 import java.util.List;
     5 import net.sf.hibernate.Criteria;
     6 import net.sf.hibernate.Query;
     7 import net.sf.hibernate.Session;
     8 import limq.exception.DaoException;
     9 
    10 public interface IBaseDao {
    11     
    12     public Session openSession();
    13     
    14     public  int getTotalCount( String hql) throws Exception;
    15     
    16     public Query getQuery(String sql) throws Exception;
    17     
    18     public Criteria getCriteria(Class clazz) throws Exception;
    19     
    20     public int getTotalPage(int totalCount,int pageSize);
    21     
    22     public void create(Object entity);
    23 
    24     public void update(Object entity);
    25 
    26     public void delete(Object entity) throws DaoException;
    27 
    28     public void deleteAll(Class clazz) throws DaoException;
    29 
    30     public void deleteAll(Collection entities) throws DaoException;
    31 
    32     public Object loadByKey(Class clazz, String keyName, Object keyValue);
    33 
    34     public List find(String queryString) throws DaoException;
    35 
    36     public List find(String queryString, Object param) throws DaoException;
    37 
    38     public List find(String queryString, Object[] params) throws DaoException;
    39 
    40 }
    41 


    BaseDao继承org.springframework.orm.hibernate.support.HibernateDaoSupport

    实现以上的 定义的方法

    如:

     1 public void create(Object entity)  { 
     2         try { 
     3             getHibernateTemplate().save(entity); 
     4             
     5         } catch (Exception e) { 
     6             log.error("保存 " + entity.getClass().getName() + " 实例到数据库失败", e); 
     7            
     8         } 
     9     } 
    10     /** 
    11      * 获得session        
    12      */ 
    13     public Session openSession() {
    14         return SessionFactoryUtils.getSession(getSessionFactory(), false);
    15     }
    16 
    17     /** 
    18      * 获得Query对象       
    19      */ 
    20     public Query getQuery(String sql) throws Exception{
    21         Session session = this.openSession();
    22         Query query = session.createQuery(sql); 
    23     return query;
    24     }
    25     /** 
    26      * 获得Criteria对象       
    27      */
    28     public Criteria getCriteria(Class clazz) throws Exception{
    29         
    30     Session session=this.openSession();
    31     Criteria criteria = session.createCriteria(clazz);
    32     return criteria;
    33     }
    34 

    可以看到,这里即充分利用了SpringHibernate的支持,还弥补了Spring的不足。最后分别为每个持久对象建立Interface,以及DAO,使其分别继承IBaseDaoBaseDao

    IDepartmentDepartmentDao

    1 public interface IDepartment extends IBaseDao {}
    2 
    3 public class DepartmentDao extends BaseDao implements IBaseDao {}
    4 

    3 Service

     在这里需要认真思考每个业务逻辑所能用到的持久层对象和DAO,还要完成配置Spring框架, 首先我一起看看applications-service.xml

      1 xml version="1.0" encoding="UTF-8"?>
      2 DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" 
      3     "http://www.springframework.org/dtd/spring-beans.dtd">
      4 <beans>
      5   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
      6     <property name="driverClassName">
      7       <value>com.mysql.jdbc.Drivervalue>
      8     property>
      9     <property name="url">
     10       <value>jdbc:mysql://localhost:3306/Studentvalue>
     11     property>
     12     <property name="username">
     13       <value>rootvalue>
     14     property>
     15     <property name="password">
     16       <value>value>
     17     property>
     18   bean>
     19   <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
     20     <property name="dataSource">
     21       <ref local="dataSource"/>
     22     property>
     23     <property name="mappingResources">
     24       <list>
     25         <value>limq/hibernate/vo/Admins.hbm.xmlvalue>
     26         <value>limq/hibernate/vo/Classes.hbm.xmlvalue>
     27         <value>limq/hibernate/vo/Courses.hbm.xmlvalue>
     28         <value>limq/hibernate/vo/Students.hbm.xmlvalue>
     29         <value>limq/hibernate/vo/ClassesInfo.hbm.xmlvalue>
     30         <value>limq/hibernate/vo/Contact.hbm.xmlvalue>
     31         <value>limq/hibernate/vo/Department.hbm.xmlvalue>
     32         <value>limq/hibernate/vo/History.hbm.xmlvalue>
     33         <value>limq/hibernate/vo/Teachers.hbm.xmlvalue>
     34       list>
     35     property>
     36     <property name="hibernateProperties">
     37       <props>
     38         <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialectprop>
     39         <prop key="hibernate.show_sql">trueprop>
     40       props>
     41     property>
     42   bean>
     43   <bean id="myTransactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
     44     <property name="sessionFactory">
     45       <ref local="sessionFactory"/>
     46     property>
     47   bean>
     48   
     49   <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
     50     <property name="sessionFactory">
     51       <ref bean="sessionFactory"/>
     52     property>
     53   bean>
     54   <bean id="studentDaoTarget" class="limq.hibernate.dao.StudentsDao">
     55     <property name="sessionFactory">
     56       <ref bean="sessionFactory"/>
     57     property>
     58   bean>
     59   <bean id="teacherDaoTarget" class="limq.hibernate.dao.TeachersDao">
     60     <property name="sessionFactory">
     61       <ref bean="sessionFactory"/>
     62     property>
     63   bean>
     64   <bean id="courseDaoTarget" class="limq.hibernate.dao.CoursesDao">
     65     <property name="sessionFactory">
     66       <ref bean="sessionFactory"/>
     67     property>
     68   bean>
     69   <bean id="classDaoTarget" class="limq.hibernate.dao.ClassesDao">
     70     <property name="sessionFactory">
     71       <ref bean="sessionFactory"/>
     72     property>
     73   bean>
     74   <bean id="departmentDaoTarget" class="limq.hibernate.dao.DepartmentDao">
     75     <property name="sessionFactory">
     76       <ref bean="sessionFactory"/>
     77     property>
     78   bean>
     79   <bean id="adminDaoTarget" class="limq.hibernate.dao.AdminDao">
     80     <property name="sessionFactory">
     81       <ref bean="sessionFactory"/>
     82     property>
     83   bean>
     84   <bean id="studentDao" class="org.springframework.aop.framework.ProxyFactoryBean">
     85     <property name="proxyInterfaces">
     86       <value>limq.hibernate.dao.IStudentsvalue>
     87     property>
     88     <property name="interceptorNames">
     89       <list>
     90         <value>hibernateInterceptorvalue>
     91         <value>studentDaoTargetvalue>
     92       list>
     93     property>
     94   bean>
     95   <bean id="teacherDao" class="org.springframework.aop.framework.ProxyFactoryBean">
     96     <property name="proxyInterfaces">
     97       <value>limq.hibernate.dao.ITeachersvalue>
     98     property>
     99     <property name="interceptorNames">
    100       <list>
    101         <value>hibernateInterceptorvalue>
    102         <value>teacherDaoTargetvalue>
    103       list>
    104     property>
    105   bean>
    106   <bean id="courseDao" class="org.springframework.aop.framework.ProxyFactoryBean">
    107     <property name="proxyInterfaces">
    108       <value>limq.hibernate.dao.ICoursesvalue>
    109     property>
    110     <property name="interceptorNames">
    111       <list>
    112         <value>hibernateInterceptorvalue>
    113         <value>courseDaoTargetvalue>
    114       list>
    115     property>
    116   bean>
    117   <bean id="classDao" class="org.springframework.aop.framework.ProxyFactoryBean">
    118     <property name="proxyInterfaces">
    119       <value>limq.hibernate.dao.IClassesvalue>
    120     property>
    121     <property name="interceptorNames">
    122       <list>
    123         <value>hibernateInterceptorvalue>
    124         <value>classDaoTargetvalue>
    125       list>
    126     property>
    127   bean>
    128   <bean id="departmentDao" class="org.springframework.aop.framework.ProxyFactoryBean">
    129     <property name="proxyInterfaces">
    130       <value>limq.hibernate.dao.IDepartmentvalue>
    131     property>
    132     <property name="interceptorNames">
    133       <list>
    134         <value>hibernateInterceptorvalue>
    135         <value>departmentDaoTargetvalue>
    136       list>
    137     property>
    138   bean>
    139   <bean id="adminDao" class="org.springframework.aop.framework.ProxyFactoryBean">
    140     <property name="proxyInterfaces">
    141       <value>limq.hibernate.dao.IAdminvalue>
    142     property>
    143     <property name="interceptorNames">
    144       <list>
    145         <value>hibernateInterceptorvalue>
    146         <value>adminDaoTargetvalue>
    147       list>
    148     property>
    149   bean>
    150   
    151   <bean id="studentManagerTarget" class="limq.spring.service.StudentsServiceImpl">
    152     <property name="studentsDao">
    153       <ref bean="studentDao"/>
    154     property>
    155     <property name="coursesDao">
    156       <ref bean="courseDao"/>
    157     property>
    158     <property name="classesDao">
    159       <ref bean="classDao"/>
    160     property>
    161     <property name="departmentsdao">
    162       <ref bean="departmentDao"/>
    163     property>
    164   bean>
    165   <bean id="teacherManagerTarget" class="limq.spring.service.TeachersServiceImpl">
    166     <property name="teachersDao">
    167       <ref bean="teacherDao"/>
    168     property>
    169     <property name="coursesDao">
    170       <ref bean="courseDao"/>
    171     property>
    172     <property name="classesDao">
    173       <ref bean="classDao"/>
    174     property>
    175     <property name="studentsDao">
    176       <ref bean="studentDao"/>
    177     property>
    178   bean>
    179   <bean id="adminManagerTarget" class="limq.spring.service.AdminServiceImpl">
    180     <property name="adminDao">
    181       <ref bean="adminDao"/>
    182     property>
    183     <property name="teachersDao">
    184       <ref bean="teacherDao"/>
    185     property>
    186     <property name="coursesDao">
    187       <ref bean="courseDao"/>
    188     property>
    189     <property name="classesDao">
    190       <ref bean="classDao"/>
    191     property>
    192     <property name="studentsDao">
    193       <ref bean="studentDao"/>
    194     property>
    195     <property name="departmentsdao">
    196       <ref bean="departmentDao"/>
    197     property>
    198   bean>
    199   
    200   <bean id="studentManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    201     <property name="transactionManager">
    202       <ref bean="myTransactionManager"/>
    203     property>
    204     <property name="target">
    205       <ref bean="studentManagerTarget"/>
    206     property>
    207     <property name="transactionAttributes">
    208       <props>
    209         <prop key="get*">PROPAGATION_SUPPORTSprop>
    210         <prop key="*">PROPAGATION_REQUIREDprop>
    211       props>
    212     property>
    213   bean>
    214   <bean id="teacherManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    215     <property name="transactionManager">
    216       <ref bean="myTransactionManager"/>
    217     property>
    218     <property name="target">
    219       <ref bean="teacherManagerTarget"/>
    220     property>
    221     <property name="transactionAttributes">
    222       <props>
    223         <prop key="get*">PROPAGATION_SUPPORTSprop>
    224         <prop key="*">PROPAGATION_REQUIREDprop>
    225       props>
    226     property>
    227   bean>
    228   <bean id="adminManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    229     <property name="transactionManager">
    230       <ref bean="myTransactionManager"/>
    231     property>
    232     <property name="target">
    233       <ref bean="adminManagerTarget"/>
    234     property>
    235     <property name="transactionAttributes">
    236       <props>
    237         <prop key="get*">PROPAGATION_SUPPORTSprop>
    238         <prop key="*">PROPAGATION_REQUIREDprop>
    239       props>
    240     property>
    241   bean>
    242 beans>
    243 


    StudentsServiceImpl以为例,下图演示了如何利用SpringIocHibernate的结合。

    可以看到分别将studentDao,classDao,coursesDao,departmentDao,注入studentManager.
    pic4.JPG

      1 IStudentsService.java
      2 public interface IStudentsService {
      3 
      4     public  boolean validate(String username,String pasword);  
      5     public Classes[] getClassesFromCourse(Courses courses);
      6     public  Department getDepFromID(Integer id);
      7     public   Courses getCourseFromID(Integer id);
      8     public   Classes getClassFromID(Integer id);
      9     public  Students getStudetFromName(String name);
     10     public  boolean ifEnrolSameCourse(Classes clazz,Students stu);
     11     public  void selectClasses(Students stu, Classes clazz,Date date);
     12     public  boolean ifMoreThanCap(Classes clazz);
     13     public void updateSudent(Students stu,Contact contact);
     14     public HashMap getCourse(PageInfo pageinfo) throws Exception;
     15     public HashMap getStudentHistory(PageInfo pageinfo,String stu_name) throws Exception;
     16  
     17 }
     18 
     19 实现StudentsServiceImpl.java
     20 public class StudentsServiceImpl implements IStudentsService {
     21 
     22     private Logger log = Logger.getLogger(this.getClass());
     23 
     24     private IStudents studentsDao;
     25 
     26     private ICourses coursesDao;
     27 
     28     private IClasses classesDao;
     29 
     30     private IDepartment departmentsdao;
     31 
     32     /**
     33      * 验证用户名密码
     34      * 
     35      * @param username
     36      *            用户名
     37      * @param password
     38      *            密码
     39      */
     40 
     41     public boolean validate(String username, String password) {
     42 
     43         String password2 = studentsDao.getPasswordFromUsername(username);
     44         if (password.equals(password2))
     45             return true;
     46         else
     47             return false;
     48 
     49     }
     50 
     51     /**
     52      * 查找所有课程
     53      *  
     54      */
     55     public Courses[] getAllCourses() {
     56 
     57         List list = null;
     58         try {
     59 
     60             list = coursesDao.find("select c from Courses as c ");
     61         } catch (Exception e) {
     62         }
     63 
     64         return (Courses[]) list.toArray(new Courses[0]);
     65     }
     66 
     67     /**
     68      *  分页显示所有课程
     69      * 
     70      * @param pageinfo
     71      */
     72     public HashMap getCourse(PageInfo pageinfo) throws Exception {
     73 
     74         HashMap hp = new HashMap();
     75         String hsql = "select c from Courses as c order by c.id";
     76         Query query = coursesDao.getQuery(hsql);
     77         int totalCount = pageinfo.getTatalCount();
     78         int totalPage = pageinfo.getTotalpage();
     79         int start = pageinfo.getStart();
     80         totalCount = totalCount == -1 ? coursesDao.getTotalCount(hsql)
     81                 : totalCount;
     82         totalPage = totalPage == -1 ? coursesDao.getTotalPage(totalCount,
     83                 pageinfo.getPageSize()) : totalPage;
     84         query.setFirstResult(start);
     85         query.setMaxResults(pageinfo.getPageSize());
     86         List list = query.list();
     87         hp.put("courses", (Courses[]) list.toArray(new Courses[0]));
     88         hp.put("totalCount"new Integer(totalCount));
     89         hp.put("totalPage"new Integer(totalPage));
     90         return hp;
     91     }
     92     /**
     93      *  分页显示所有选课历史
     94      * @param pageinfo 
     95      * @param stu_name
     96      */
     97     public HashMap getStudentHistory(PageInfo pageinfo, String stu_name)
     98             throws Exception {
     99         HashMap hp = new HashMap();
    100         Students stu = this.getStudetFromName(stu_name);
    101         Integer stu_id = stu.getId();
    102         Criteria criteria = coursesDao.getCriteria(History.class);
    103         criteria.createCriteria("student").add(Expression.eq("name", stu_name));
    104         int totalCount = pageinfo.getTatalCount();
    105         int totalPage = pageinfo.getTotalpage();
    106         int start = pageinfo.getStart();
    107         totalCount = totalCount == -1 ? criteria.list().size() : totalCount;
    108         totalPage = totalPage == -1 ? studentsDao.getTotalPage(totalCount,
    109         pageinfo.getPageSize()) : totalPage;
    110         criteria.setFirstResult(start);
    111         criteria.setMaxResults(pageinfo.getPageSize());
    112         criteria.addOrder(Order.asc("id"));
    113         List list = criteria.list();
    114         hp.put("history", (History[]) list.toArray(new History[0]));
    115         hp.put("totalCount"new Integer(totalCount));
    116         hp.put("totalPage"new Integer(totalPage));
    117         return hp;
    118     }
    119     /**
    120      * 根据课程查找班级
    121      * @param course
    122      *            课程实体
    123      * @return 返回该课程下所有班级
    124      */
    125     public Classes[] getClassesFromCourse(Courses course) {
    126         return coursesDao.getClassesFromCourse(course);
    127     }
    128 
    129     /**
    130      * 根据主键查找系
    131      * @param id
    132      *            主键ID
    133      */
    134     public Department getDepFromID(Integer id) {
    135         return (Department) departmentsdao
    136                 .loadByKey(Department.class"id", id);
    137     }
    138 
    139     /**
    140      * 根据主键查找课程
    141      * @param id
    142      *            主键ID
    143      */
    144     public Courses getCourseFromID(Integer id) {
    145         return (Courses) coursesDao.loadByKey(Courses.class"id", id);
    146     }
    147     /**
    148      * 根据主键查找班级
    149      * @param id
    150      *            主键ID
    151      */
    152     public Classes getClassFromID(Integer id) {
    153         return (Classes) classesDao.loadByKey(Classes.class"id", id);
    154     }
    155 
    156     /**
    157      * 根据姓名查找学生
    158      * @param name
    159      */
    160     public Students getStudetFromName(String name) {
    161         return (Students) studentsDao.loadByKey(Students.class"name", name);
    162     }
    163 
    164     /**
    165      * 检查学生是否选报了同一课程的班级
    166      * @param clazz
    167      *            所选报的班级
    168      * @param stu
    169      *            学生实体
    170      * @return true 该生选报同一课程的班级
    171      * @return false 没有报过该课程的班级,可以选报
    172      *  
    173      */
    174     public boolean ifEnrolSameCourse(Classes clazz, Students stu) {
    175 
    176         Courses cour = clazz.getCourse();
    177 
    178         Classes[] classes = (Classes[]) stu.getClasses()
    179                 .toArray(new Classes[0]);
    180         for (int i = 0; i < classes.length; i++) {
    181 
    182             Courses c1 = classes[i].getCourse();
    183 
    184             if (c1.getId().equals(cour.getId()))
    185                 return true;
    186         }
    187         return false;
    188     }
    189 
    190     /**
    191      * 检查课程的目前人数 
    192      * @param clazz
    193      *            检查班级人数是否已满
    194      * @param clazz
    195      *            班级实体
    196      * @return true 班级人数已满
    197      * @return false 班级人数未满
    198      *  
    199      */
    200     public boolean ifMoreThanCap(Classes clazz) {
    201         Integer capacity = clazz.getCapacity();
    202         Integer maxcapacity = clazz.getMaxcapacity();
    203         if (capacity.intValue() < maxcapacity.intValue()) {
    204             clazz.setCapacity(Integer.valueOf(capacity.intValue() + 1));
    205             //classesDao.update(clazz);
    206             return false;
    207         } else
    208             return true;
    209 
    210     }
    211 
    212     /**
    213      * 数据库插入选择班级的记录
    214      * @param stu
    215      *            学生
    216      * @param clazz
    217      *            所选择的班级
    218      */
    219     public void selectClasses(Students stu, Classes clazz, Date date)
    220  {
    221         stu.getClasses().add(clazz);
    222         clazz.getStudents().add(stu);          
    223         History his = new History();
    224         his.setEnrolTime(date);
    225         his.setStudent(stu);
    226         his.setClasses(clazz);
    227         his.setScore(clazz.getCourse().getScore());
    228         his.setMarking(new Double(0));
    229         try{
    230         String cour_name=new String(clazz.getCourse().getName().getBytes("GBK"));       
    231         his.setCourseName(cour_name);
    232         }catch( java.io.UnsupportedEncodingException e){e.getStackTrace();}       
    233         stu.getHistory().add(his);
    234     }
    235 
    236     public void updateSudent(Students stu,Contact contact){
    237         
    238        studentsDao.update(stu);
    239        studentsDao.update(contact);
    240     
    241     }
    242     public IStudents getStudentsDao() {
    243         return studentsDao;
    244     }
    245     public void setStudentsDao(IStudents studentsDao) {
    246         this.studentsDao = studentsDao;
    247     }
    248     public IClasses getClassesDao() {
    249         return classesDao;
    250     }
    251     public void setClassesDao(IClasses classesDao) {
    252         this.classesDao = classesDao;
    253     }
    254     public ICourses getCoursesDao() {
    255         return coursesDao;
    256     }
    257     public void setCoursesDao(ICourses coursesDao) {
    258         this.coursesDao = coursesDao;
    259     }
    260     public IDepartment getDepartmentsdao() {
    261         return departmentsdao;
    262     }
    263     public void setDepartmentsdao(IDepartment departmentdao) {
    264         this.departmentsdao = departmentdao;
    265     }
    266 }
    267 
    268 


    4 UI

    这里我们选择Struts,首先配置 web.xml

     1 xml version="1.0" encoding="UTF-8"?>
     2 <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.4" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
     3   <context-param>
     4     <param-name>contextConfigLocationparam-name>
     5     <param-value>/WEB-INF/classes/applications-service.xmlparam-value>
     6   context-param>
     7   <context-param>
     8     <param-name>log4jConfigLocationparam-name>
     9     <param-value>/WEB-INF/log4j.propertiesparam-value>
    10   context-param>
    11   <filter>
    12     <filter-name>hibernateFilterfilter-name>
    13     <filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilterfilter-class>
    14   filter>
    15   <filter-mapping>
    16     <filter-name>hibernateFilterfilter-name>
    17     <url-pattern>/*url-pattern>
    18   filter-mapping>
    19   <filter>
    20     <filter-name>Set Character Encodingfilter-name>
    21     <filter-class>limq.struts.SetCharacterEncodingFilterfilter-class>
    22   filter>
    23   <filter-mapping>
    24     <filter-name>Set Character Encodingfilter-name>
    25     <url-pattern>/*url-pattern>
    26   filter-mapping>
    27   <servlet>
    28     <servlet-name>SpringContextServletservlet-name>
    29     <servlet-class>org.springframework.web.context.ContextLoaderServletservlet-class>
    30     <load-on-startup>1load-on-startup>
    31   servlet>
    32   <servlet>
    33     <servlet-name>actionservlet-name>
    34     <servlet-class>org.apache.struts.action.ActionServletservlet-class>
    35     <init-param>
    36       <param-name>configparam-name>
    37       <param-value>/WEB-INF/struts-config.xmlparam-value>
    38     init-param>
    39     <init-param>
    40       <param-name>debugparam-name>
    41       <param-value>3param-value>
    42     init-param>
    43     <init-param>
    44       <param-name>detailparam-name>
    45       <param-value>3param-value>
    46     init-param>
    47     <load-on-startup>0load-on-startup>
    48   servlet>
    49   <servlet-mapping>
    50     <servlet-name>actionservlet-name>
    51     <url-pattern>*.dourl-pattern>
    52   servlet-mapping>
    53 web-app>
    54 
    55 

    其中注意这几句,

    1 <filter>
    2     <filter-name>hibernateFilterfilter-name>
    3 <filter-class>org.springframework.orm.hibernate.support.OpenSessionInViewFilterfilter-class>
    4   filter>
    5 <filter-mapping>
    6     <filter-name>hibernateFilterfilter-name>
    7     <url-pattern>/*url-pattern>
    8 filter-mapping>
    9 


    由于我们使用了lazy = "true"如果想在UI层使用实体对象关联来获得其他对象时就会有这样的提示:

    org.hibernate.LazyInitializationException: failed to lazily initialize a collection

    Spring 中引入了 OpenSessionInView模式可以处理以上问题,即在web.xml中加入以上代码。

     

     

    接下来建立抽象BaseAction,和 BaseDispatchAction,其中后者与前者相似目的为减少Action的数量

     1 abstract class BaseAction extends Action {
     2 
     3     private IStudentsService studentsService;
     4     private ITeachersService teachersSerivce;
     5     private IAdminService adminService;
     6     public void setServlet(ActionServlet actionServlet) {
     7         super.setServlet(actionServlet);
     8         ServletContext servletContext = actionServlet.getServletContext();
     9         WebApplicationContext wac = WebApplicationContextUtils
    10                 .getRequiredWebApplicationContext(servletContext);
    11 
    12         this.studentsService = (IStudentsService) wac.getBean("studentManager");
    13         this.adminService = (IAdminService) wac.getBean("adminManager");
    14         this.teachersSerivce = (ITeachersService) wac.getBean("teacherManager");
    15     }
    16     public IStudentsService getStudentsService() {
    17         return studentsService;
    18     }
    19     public ITeachersService getTeachersSerivce() {
    20         return teachersSerivce;
    21     }
    22     public void setTeachersSerivce(ITeachersService teachersSerivce) {
    23         this.teachersSerivce = teachersSerivce;
    24     }
    25     public IAdminService getAdminService() {
    26         return adminService;
    27     }
    28     public void setAdminService(IAdminService adminService) {
    29         this.adminService = adminService;
    30     }
    31 }
    32 


    BaseDispatchAction与之类似,请查看源码。其他Action都从这两个类继承。

    以下就以查看课程下的班级为例演示StrutsSpring的使用:

     1 CoursesAction.java
     2     /** 
     3      * 查看课程下的班级 
     4      */ 
     5     public ActionForward viewClassFromCourse(ActionMapping mapping,
     6             ActionForm form, HttpServletRequest request,
     7             HttpServletResponse response) throws Exception {
     8         Integer cour_id = Integer.valueOf((request.getParameter("cour_id")));
     9         Courses cour = super.getStudentsService().getCourseFromID(cour_id);
    10         Classes[] clazz =(Classes[])cour.getClasses().toArray(new Classes[0]);
    11         request.setAttribute("clazz", clazz);
    12         return mapping.findForward("success");
    13 }
    14 

    这里从上一个页面获得课程编号 cour_id, 然后通过StudentsServiceImpl中的

    1 public Courses getCourseFromID(Integer id) {
    2         return (Courses) coursesDao.loadByKey(Courses.class"id", id);
    3 }
    4 

    方法查到Courses实例,利用CoursesClasses的关联关系得到Classes[],在将其放入

    Request. 通过mapping.findForward("success"),转发到

    select_course_Content.jsp


    CustomRequestProcessor.java 介绍

     1 public class CustomRequestProcessor extends RequestProcessor {
     2     protected boolean
     processPreprocess(HttpServletRequest request,
     3 
                HttpServletResponse response) {
     4         boolean continueProcessing = true
    ;
     5         HttpSession session =
     request.getSession();
     6         String uri =
    request.getRequestURI();
     7         if ( session == null || session.getAttribute("userName"== null
     ) {
     8             continueProcessing = false
    ;  
     9         if(uri.endsWith("login.do")) return true
    ;    
    10         try
    {
    11             response.sendRedirect("/StudentManger/login.jsp"
     );
    12           }catch
    ( Exception ex ){
    13             log.error( "Problem sending redirect from processPreprocess()"
     );
    14 
              }
    15 
            }
    16         return
     continueProcessing;
    17 
        }
    18 
    }
    19 


    为了验证用户操作权限,这里扩展了Struts RequestProcessor来判断Session如果SessionuserName都不空则程序继续,否则重定向到login.jsp。要想扩展RequestProcessor类,需在Struts的配置文件中加入

    1 <controller 
    2 contentType="text/html;charset=UTF-8"
    3 locale="true" 
    4 nocache="true" 
    5 processorClass="limq.struts.CustomRequestProcessor"/>
    6 

    呵呵,当然在正规使用时仅仅这样验证是不够的。欢迎你把自己修改方法告诉我。

     

    4分页处理:

    下面重点讨论一下Hibernate的分页处理方式。

    Hibernate 中处理查询主要有 Query Criteria,分别以 HSQL或编程方式实现,

    本例对这两种方法都有相关处理。由于在Spring中无法直接使用QueryCriteria对象

    所以只有先从Spring那里借一个Session,等使用完了在还给Sping处理。读者应该还记得在BaseDao中有这样的语句方便我们获取Session及其他对象:

     

     1     public Query getQuery(String sql) throws Exception{
     2         Session session = this.openSession();
     3         Query query = session.createQuery(sql); 
     4     return query;
     5     }
     6    
     7     public Criteria getCriteria(Class clazz) throws Exception{
     8         
     9     Session session=this.openSession();
    10     Criteria criteria = session.createCriteria(clazz);
    11     return criteria;
    12     }
    13 

    Service层以查询所有课程与学生选课记录为例处理QueryCriteria

     1  StudentsServiceImpl.java
     2     public HashMap getCourse(PageInfo pageinfo) throws Exception {
     3 
     4         HashMap hp = new HashMap();
     5         String hsql = "select c from Courses as c order by c.id";
     6         Query query = coursesDao.getQuery(hsql);
     7         int totalCount = pageinfo.getTatalCount();
     8         int totalPage = pageinfo.getTotalpage();
     9         int start = pageinfo.getStart();
    10         totalCount = totalCount == -1 ? coursesDao.getTotalCount(hsql)
    11                 : totalCount;
    12         totalPage = totalPage == -1 ? coursesDao.getTotalPage(totalCount,
    13                 pageinfo.getPageSize()) : totalPage;
    14         query.setFirstResult(start);
    15         query.setMaxResults(pageinfo.getPageSize());
    16         List list = query.list();
    17         hp.put("courses", (Courses[]) list.toArray(new Courses[0]));
    18         hp.put("totalCount"new Integer(totalCount));
    19         hp.put("totalPage"new Integer(totalPage));
    20         return hp;
    21     }
    22    
    23     public HashMap getStudentHistory(PageInfo pageinfo, String stu_name)
    24             throws Exception {
    25         HashMap hp = new HashMap();
    26         Students stu = this.getStudetFromName(stu_name);
    27         Integer stu_id = stu.getId();
    28         Criteria criteria = coursesDao.getCriteria(History.class);
    29         criteria.createCriteria("student").add(Expression.eq("name", stu_name));
    30         int totalCount = pageinfo.getTatalCount();
    31         int totalPage = pageinfo.getTotalpage();
    32         int start = pageinfo.getStart();
    33         totalCount = totalCount == -1 ? criteria.list().size() : totalCount;
    34         totalPage = totalPage == -1 ? studentsDao.getTotalPage(totalCount,
    35         pageinfo.getPageSize()) : totalPage;
    36         criteria.setFirstResult(start);
    37         criteria.setMaxResults(pageinfo.getPageSize());
    38         criteria.addOrder(Order.asc("id"));
    39         List list = criteria.list();
    40         hp.put("history", (History[]) list.toArray(new History[0]));
    41         hp.put("totalCount"new Integer(totalCount));
    42         hp.put("totalPage"new Integer(totalPage));
    43         return hp;
    44     }
    45 PageIngfo.java
    46 public class PageInfo  {
    47     
    48     int pageNo=0;
    49     int totalpage=-1;
    50     int tatalCount=-1;
    51     int pageSize=0;
    52 int start=0;
    53 
    54 


    可以看到getCoursegetStudentHistory有很多相似之处,HibernateQueryCriteria提供了针对不同数据库的解决分页方法, Quey需要我们写HSQL Criteria不但可以应付带有条件的查询,还不用我们自己写HSQLPageInfo是含有分页信息的普通java类。

    再看看Struts是如何调用getStudentHistory 的,

     1 PageAction.java
     2 public class PageAction  extends BaseDispatchAction{
     3     public ActionForward execute(ActionMapping mapping,
     4              ActionForm form,
     5              HttpServletRequest request,
     6              HttpServletResponse response)
     7 throws Exception {
     8         String pageNo=request.getParameter("pageNo");
     9         String totalcount=request.getParameter("totalcount");
    10         String totalpage=request.getParameter("totalpage");
    11         int pagesize=2;//每页的大小
    12         PageInfo page =new PageInfo();
    13         page.setPageSize(pagesize);
    14         HashMap hp=null;
    15         History[] historys = null;
    16         String stu_name=null;
    17         HttpSession session = request.getSession();
    18         stu_name = (String) session.getAttribute("userName"); 
    19         if(pageNo == null || totalcount == null || totalpage==null){
    20         //第一次发送请求
    21             page.setPageNo(1);           
    22             hp=super.getStudentsService().getStudentHistory(page,stu_name);
    23             page.setTatalCount(((Integer)hp.get("totalCount")).intValue());
    24             page.setTotalpage(((Integer)hp.get("totalPage")).intValue());      
    25         }else{
    26             page.setPageNo(Integer.parseInt(pageNo));
    27             page.setTatalCount(Integer.parseInt(totalcount));
    28             page.setTotalpage(Integer.parseInt(totalpage));
    29            hp=super.getStudentsService().getStudentHistory(page,stu_name);
    30            
    31         }
    32      historys =(History[]) hp.get("history");
    33      request.setAttribute("history",historys);
    34      request.setAttribute("pageinfo",page);    
    35         return mapping.findForward("success");
    36     }
    37 }
    38 


    stu_his_Content.jsp中避免代码重复使用了自定义标志来处理分页

     1 <%@ page contentType="text/html;charset=UTF-8" language="java"  %> 
     2 <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
     3 <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
     4 <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
     5 <%@ page import="limq.hibernate.vo.*"%>
     6 <%@ taglib uri="/WEB-INF/MyTag.tld" prefix="mytag"%>
     7 <%@ page import="limq.common.*"%>
     8 <html:html locale="true"> 
     9   <body>
    10   <%
    11   PageInfo pageinfo =(PageInfo) request.getAttribute("pageinfo");
    12   History[] historys = (History[])request.getAttribute("history");
    13   %>
    14 <table width="550" border="1" cellspacing="0" align="center" cellpadding="0">
    15   <tr>
    16     <td><bean:message key="class.id"/>td>
    17     <td><bean:message key="course.name"/>td>
    18     <td><bean:message key="enrol.time"/>td>
    19     <td><bean:message key="score"/>td>
    20     <td><bean:message key="marking"/>td>
    21   tr>
    22   <%
    23   for(int i=0;i<historys.length;i++){
    24   History  his=historys[i];
    25   %>
    26   <tr>
    27     <td><%=his.getClasses().getId()%>td>
    28     <td><%=his.getCourseName()%>td>
    29     <td><%=his.getEnrolTime()%>td>
    30     <td><%=his.getScore()%>td>
    31     <td><%=his.getMarking()%>td>
    32   tr>
    33   <%
    34   }
    35   %>
    36 table>
    37 <mytag:page pageinfo="<%=pageinfo%>" action="getHistory.do"/>
    38 body>
    39 html:html>
    40 


    标志处理类如下:

     1 PageTag.java
     2 
     3 public class PageTag extends SimpleTagSupport {
     4 
     5     private PageInfo pageinfo = null;
     6 private String action = null;
     7 
     8     public String getAction() {
     9         return action;}
    10     public void setAction(String action) {
    11         this.action = action;
    12     }
    13     public PageInfo getPageinfo() {
    14         return pageinfo;
    15     }
    16     public void setPageinfo(PageInfo pageinfo) {
    17         this.pageinfo = pageinfo;
    18     }
    19 
    20     public void doTag() throws JspException, IOException {
    21         JspWriter out = getJspContext().getOut();
    22 
    23         int totalpage = pageinfo.getTotalpage();
    24         int totalcount = pageinfo.getTatalCount();
    25         int pageNo = pageinfo.getPageNo();
    26         int addPageNo = pageNo + 1;
    27         int minPageNo = pageNo - 1;
    28 
    29         out.println("
    ");
    66 
    67     }
    68 
    69 }
    70 


    5
    中文乱码问题:

    1 数据库:MYSQL 4.1 (或以上版本)4.1直接支持Unicode,以下版本支持的不好。

    2 驱动: MySQL JDBC Driver3.0.16(或以上版本)

    3 在数据库中做如下设定

    pic5.JPG

    4 在建立表时同样加上ENGINE=MyISAM DEFAULT CHARSET=gbk

    1CREATE TABLE `students` (
    2  `id` int(20NOT NULL default '0',
    3  `name` varchar(20NOT NULL default '',
    4  `department_id` int(11default NULL,
    5  `password` varchar(20default NULL,
    6  `score` double(15,3default NULL,
    7  PRIMARY KEY  (`id`)
    8) ENGINE=MyISAM DEFAULT CHARSET=gbk
    9

    5 配置hibernate.cfg.xml

    1 <property name="connection.url">jdbc:mysql://localhost:3306/Studentproperty>
    2 <property name="dialect">net.sf.hibernate.dialect.MySQLDialectproperty>
    3 <property name="connection.password">property>
    4 <property name="connection.driver_class">com.mysql.jdbc.Driverproperty>
    5 

    robbin MySQL JDBC Driver3.0.16也是一个分水岭,3.0.16版本会取数据库本身的编码,然后按照该编码转换,这种方式和OracleJDBC Driver是一样的。例如你的数据库是GBK编码的话,JDBC Driver就会把数据库里面的取出来的字符串按照GBKunicode转换,送给JVM。因此正确的设置数据库本身的编码就尤为重要。

    MySQL JDBC Driver3.0.16以下的版本则不然,它不会那么智能的根据数据库编码来确定如何转换,它总是默认使用ISO8859-1,因此你必须使用 characterEncoding=GBK来强制他把数据库中取出来的字符串按照GBK来往unicode转换。
    因此,使用什么数据库版本,不管是3.x,还是4.0.x还是4.1.x,其实对我们来说不重要,重要的有二:

    1)
    正确的设定数据库编码,MySQL4.0以下版本的字符集总是默认ISO8859-1MySQL4.1在安装的时候会让你选择。如果你准备使用UTF- 8,那么在创建数据库的时候就要指定好UTF-8(创建好以后也可以改,4.1以上版本还可以单独指定表的字符集)
    2)
    使用3.0.16以上版本的JDBC Driver,那么你就不需要再写什么characterEncoding=UTF-8

     

    6 开发工具介绍

    MyEclipse 3.8

    首先添加用户库,如下图将Struts,Spring,Hibernate 的库添加到用户库中

    pic6.JPG

    如果出现环境问题可能你的Struts包有问题,请到http://struts.apache.org/download.cgi下载struts-1.2.7-lib.zip

    具体使用参考http://www.laliluna.de/struts-hibernate-integration-tutorial-en.html

    总结

    本文至此已将Struts+Sprng+Hibernate的大致思路以及本人所遇到的难点,重点介绍完了。

    其中管理员我只完成了对学生的部分,其他功能大同小异,有兴趣的读者不妨动手试试。最后建议初学者不要直接使用SpringHibernate的封装,而是从Hibernate学起,先要学会自己管理SessionTransaction,然后在用Spring,这样理解会更深刻。同时如果你有好的建议,或问题请联系我

    QQ 39315890

    Email: mill_lmq@yahoo.com.cn

     
  • 相关阅读:
    2. Add Two Numbers
    8. String to Integer (atoi)
    18. 4Sum
    15. 3Sum
    1. Two Sum
    227. Basic Calculator
    7. Reverse Integer
    PostMessage和SendMessage的区别
    Date Time Picker控件
    git 设置和取消代理
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6470886.html
Copyright © 2011-2022 走看看