Struts+Spring+Hibernate开发实例

来源:互联网 发布:linux下如何拷贝文件夹 编辑:程序博客网 时间:2024/05/18 02:28
Struts+Spring+Hibernate开发实例
本文并不想介绍Struts,Spring,Hibernate的原理系统架构等,本文地目的是通过一个较复杂地实例介绍如何整合Struts,Spring,Hibernate,网上现有的例子虽然也能达到目的,但功能都比较单一,复杂的例子时会有意想不到的麻烦。本文对读者假设已经具备了以上框架的基础知识。以及那些已经了解Struts,Spring,Hibernate的基本概念,但是还没有亲身在较复杂的项目中体验Struts+Spring+Hibernate的开发人员。
1 Struts
   虽然不打算过多介绍Struts的原理,但是大概介绍一下还是有必要的。Struts本身就是 MVC 在这里负责将用户数据传人业务层,以及 将业务层处理的结果返回给用户,此系统属于较简单WEB应用,采用了OpenSessionInView模式处理LazyLoad问题,这样我们可以在用户视图中使用 get,set方法来方便地获取关联对象。为了处理庞大的Action和ActionForm问题,在此我门准备使用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层,StudentsServiceImpl,TeachersServiceImpl,AdminServiceImpl。
 
3 Hibernate
 有了Spring的封装,我们要对Hibernate做的就是正确实现对象关系的映射。由于此处处于系统的最底层,准确无误的实现对象之间的关联关系映射将起着至关重要的作用。
 总之,理解了Struts,Spring,Hibernate地原理以及之间的关系之后,剩下的工作就如同在以Spring为核心的Struts为表现的框架中堆积木。
下图可以更好的帮助我们理解StrutsSpringHibernate之间的关系。
pic1.JPG

案例简述
设计思路主要源于 大学选修课,该系统可以方便处理学生在课程选报,学分查询,成绩查询,以及 成绩发布等。
系统以班级为核心,一门课程可以对应多个班级,一名教师也可以带不同的班级,学生可以选报不同课程所对应的班级,班级自身有目前人数,和最大人数,以及上课时间,上课地点的属性。
学生在选报班级之后,班级的人数会自动加一,直到等于最大人数时,其他学生将会有人数已满的错误提示。同理如果学生选择了同一课程的不同班级,也将收到错误提示。学生有密码,系别,学分,地址,电话等属性。
教师在系统中主要负责成绩发布,教师可以对其所带的班级的学生的成绩修改,系统会以成绩是否大于等于60来判断学生是否通过考试,如果通过会将该课程的学分累加到学生学分,同样如果教师二次修改了成绩,而且小于60,系统会在学生学分上扣掉该课程的分数。
课程在系统中具体体现为班级,自身带有学分属性。
系有编号,名称的属性,同时可以作为联系教师,课程,学生的桥梁。
 
功能模块
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 
用过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 以及对应的get,set 方法,History.java 中加入
private Students student;
public Students getStudent() {
        return student;
    }
  
 public void setStudent(Students student) {
        this.student = student;
    }
具体内容请查看 源代码。

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以为例,下图演示了如何利用Spring的Ioc与Hibernate的结合。
可以看到分别将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 
 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中的
方法查到Courses实例,利用Courses和Classes的关联关系得到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如果Session和userName都不空则程序继续,否则重定向到login.jsp。要想扩展RequestProcessor类,需在Struts的配置文件中加入
呵呵,当然在正规使用时仅仅这样验证是不够的。欢迎你把自己修改方法告诉我。
 
4分页处理:
下面重点讨论一下Hibernate的分页处理方式。
Hibernate 中处理查询主要有 Query ,Criteria,分别以 HSQL或编程方式实现,
本例对这两种方法都有相关处理。由于在Spring中无法直接使用Query和Criteria对象
所以只有先从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层以查询所有课程与学生选课记录为例处理Query与Criteria
 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 

可以看到getCourse和getStudentHistory有很多相似之处,Hibernate为Query和Criteria提供了针对不同数据库的解决分页方法, Quey需要我们写HSQL, Criteria不但可以应付带有条件的查询,还不用我们自己写HSQL,PageInfo是含有分页信息的普通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  
 2 
 3 
 4 
 5 
 6 
 7 
 8 <html:html locale="true"> 
 9   <body>
10   
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   
26   <tr>
27     <td>td>
28     <td>td>
29     <td>td>
30     <td>td>
31     <td>td>
32   tr>
33   
36 table>
37 <mytag:page 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(""400/" align=/"center/"  cellPadding=/"0/" cellSpacing=/"0/"");
30         out.print("");
31         out.println("" + totalcount + "条," + totalpage + "页,当前"
32                 + pageNo + "
1 <controller 
2 contentType="text/html;charset=UTF-8"
3 locale="true" 
4 nocache="true" 
5 processorClass="limq.struts.CustomRequestProcessor"/>
6 
1 public Courses getCourseFromID(Integer id) {
2         return (Courses) coursesDao.loadByKey(Courses.class"id", id);
3 }
4 

由于我们使用了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都从这两个类继承。
以下就以查看课程下的班级为例演示Struts与Spring的使用:
2 DAO 数据访问层
首先,编写IBaseDao与BaseDao,其中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
实现以上的 定义的方法
如:
可以看到,这里即充分利用了Spring对Hibernate的支持,还弥补了Spring的不足。最后分别为每个持久对象建立Interface,以及DAO,使其分别继承IBaseDao与BaseDao。
如IDepartment,DepartmentDao
 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 
同样在History.cfg.xml中加入:
1  <many-to-one name="student"
2                   class="limq.hibernate.vo.Students"
3                   column="student_id"  >    
4      many-to-one>
5 
介绍
");
33         out.println(" ");
34         if (pageNo > 1) {
35             out
36                     .println("&"/StudentManger/" + action
37                             + "?pageNo=1"+ "&totalpage=" + totalpage + "&totalcount="
38                     + totalcount + "/">" );
39         }
40         out.print("首页");
41         out.println(" ");
42         if (pageNo > 1) {
43             out.println("&"/StudentManger/" + action + "?pageNo="
44                     + minPageNo + "&totalpage=" + totalpage + "&totalcount="
45                     + totalcount + "/">");
46         }
47         out.print("上页");
48         out.println(" ");
49         if (pageNo < totalpage) {
50             out.println("&"/StudentManger/" + action + "?pageNo="
51                     + addPageNo + "&totalpage=" + totalpage + "&totalcount="
52                     + totalcount + "/">");
53         }
54         out.print("下页");
55         out.println(" ");
56         if (pageNo < totalpage) {
57 
58             out.println(""/StudentManger/" + action + "?pageNo="
59                     + totalpage + "&totalpage=" + totalpage + "&totalcount="
60                     + totalcount + "/">");
61 
62         }
63         out.print("末页");
64         out.println(" ");
65         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
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 Driver的3.0.16也是一个分水岭,3.0.16版本会取数据库本身的编码,然后按照该编码转换,这种方式和Oracle的JDBC Driver是一样的。例如你的数据库是GBK编码的话,JDBC Driver就会把数据库里面的取出来的字符串按照GBK往unicode转换,送给JVM。因此正确的设置数据库本身的编码就尤为重要。
MySQL JDBC Driver3.0.16以下的版本则不然,它不会那么智能的根据数据库编码来确定如何转换,它总是默认使用ISO8859-1,因此你必须使用 characterEncoding=GBK来强制他把数据库中取出来的字符串按照GBK来往unicode转换。
因此,使用什么数据库版本,不管是3.x,还是4.0.x还是4.1.x,其实对我们来说不重要,重要的有二:

1) 正确的设定数据库编码,MySQL4.0以下版本的字符集总是默认ISO8859-1,MySQL4.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的大致思路以及本人所遇到的难点,重点介绍完了。
其中管理员我只完成了对学生的部分,其他功能大同小异,有兴趣的读者不妨动手试试。最后建议初学者不要直接使用Spring对Hibernate的封装,而是从Hibernate学起,先要学会自己管理Session,Transaction,然后在用Spring,这样理解会更深刻。同时如果你有好的建议,或问题请联系我
QQ 39315890
Email:mill_lmq@yahoo.com.cn
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
  
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 阿根廷认证出口声明成分错了怎么办 花盆土里面有白色的虫子怎么办 刚买的月季苗叶子黄了怎么办? 月季新出的芽中间黑了怎么办 龙须的茎被折断了怎么办? 扦插的月季跟部总发黑怎么办 用过皮炎平后的黑印怎么办 兰花现在不管王莽岭了员工怎么办 家里很穷妈妈还不知道省钱怎么办 执业医师电子注册信息弄错了怎么办 开过花后的百合花根怎么办 荔枝吃起来有股保鲜剂的味道怎么办 厂停产不宣布倒闭又不赔钱怎么办 二审判决生效后发现判错了怎么办 应收账款质押后附属的担保怎么办 房子借款合同和抵押合同丢了怎么办 离婚判决不服上诉期限过了怎么办 法院判完执行厅不执行怎么办 民事判决书下来又有新的证据怎么办 民事判决书下来欠钱没钱法院怎么办 法院笔录没看清就签字了怎么办 有人模仿自己笔迹在法院签字怎么办 房屋未签合同中介定金不退怎么办 临时摊位买的东西想退怎么办 租房合同签了房东不想租了怎么办 租房合同签了不想租了怎么办 租房合同刚签一天不想租怎么办 买二手房房东不交物业费怎么办 买二手房原房主欠物业费怎么办 客人将物品遗留在餐厅时怎么办 工程签合同了又别人来干怎么办? 超市储存柜东西忘拿了怎么办 普通异性朋友出去玩在外面住怎么办 古墓丽影崛起绳箭突然没有了怎么办 pp材质的水杯用开水烫了怎么办 手上长水泡很痒怎么办有什么药膏 烧伤后水泡破了周围都肿了怎么办 烧伤的水泡破了碰到水怎么办 浓硫酸沾到皮肤上应该怎么办 将浓硫酸沾到皮肤上怎么办 刷厕所的盐酸弄到皮肤上怎么办