# SimpleCrm
**Repository Path**: magic_duck/SimpleCrm
## Basic Information
- **Project Name**: SimpleCrm
- **Description**: 这是一个用于整合SSH框架的练手项目,模拟维护学生和学校之间的关系的CRM管理系统。
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 0
- **Created**: 2017-07-16
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# SimpleCrm笔记
#### 导语:
> [项目地址](https://git.oschina.net/magic_duck/SimpleCrm) 这是一个阉割版的CRM关系管理系统,由于是练手项目,只是用于学习完SSH后进行整合测试,由于数据库表设计有部分问题,项目有少许功能没有进行制作,望见谅。
## 项目效果截图如下:

## 项目数据库表关系如下:

## 登录拦截器解决方案:
先声明拦截器:
``` xml
```
方案一:每一个 action 单独使用,需要多次引用,否则默认将被覆盖。
``` xml
```
方案二:将多个拦截器打包生成自定义栈,配置 action 使用栈
``` xml
```
方案三:将自定义栈,把默认栈覆盖
``` xml
```
## web层访问 Hibernate 延迟加载数据抛出异常解决方案:
原因:Hibernate 允许对关联对象、属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Session 范围之内进行。如果 Service 层返回一个启用了延迟加载功能的领域对象给 Web 层,当 Web 层访问到那些需要延迟加载的数据时,由于加载领域对象的 Hibernate Session 已经关闭,这些导致延迟加载数据的访问异常。
解决方案:spring 为我们解决 hibernate 的 Session 的关闭与开启问题,只需配置 OpenSessionInVIewFilter 过滤器,此过滤器用来把一个 Hibernate Session 和一次完整请求过程对应的线程相绑定。目的时为了实现"Open Session in View"的模式。它允许在事务提交之后延迟加载显示所需要的对象。
关于配置:web.xml中的配置要注意先后顺序,OpenSessionInViewFilter要在前端控制器前面
``` xml
openSession
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
openSession
/*
```
缺点:系统的性能会因为用户的网络状况受到影响,当 request 在生成页面完成后,session 才会被释放,所以如果用户的网络状况比较差,那么连接池中的链接会迟迟不被回收,造成内存增加,系统性能受损。
## 使用 ValueStack 与 ActionContext 存放数据的选择方案:
首先需要明确两者区别:
> 相同点:两者都是在一次HTTP请求的范围内使用的。
> 不同点:值栈时栈结构,ActionContext 是映射 (Map) 结构的。
方案一:context (map) 存放 put(key, value),jsp页面获取数据需要通过 "#key"
``` java
ActionContext.getContext().put(key, value);
```
方案二:root (值栈) push(obj),一般存放 JavaBean 或 Map ,jsp页面获取数据直接通过: "属性名" 或 "key"
``` java
ActionContext.getContext().getValueStack().push(o);
```
方案三:root (值栈) set(key, value),一般用来存放list,jsp页面获取直接通过 "key"
``` java
// set方法底层 new Map(key, value),然后将其 push(map)
ActionContext.getContext().getValueStack().set(key, value);
```
## 使用 HibernateCallback 回调方法管理数据库:
前言:我们使用 HibernateTemplate 有一个很重要的原因就在于我们不想直接控制事务,不想直接去获取,打开 Session,开始一个事务,处理异常,提交一个事务,最后关闭Session,我们使用框架就是为了专注于业务,不想去做这些重复而繁琐的操作。所以我们使用 Hibernate 将这些责任委托给 HibernateTemplate ,然后使用声明式的配置来实现这样的功能。
如果我们直接通过 this.getSession().createQuery(sql) 这样的方式来管理数据库,那就意味着我们放弃了上面所说的一切好处,原因可参阅此博客:[getHibernateTemplate()和getSession()的区别](http://www.cnblogs.com/xulisha123/p/5015183.html) ,然而有时我们确实需要使用到 Query 对象来查询,如调用 [ query.setFirstResult(startIndex); query.setMaxResults(pageSize); ], 但是 HibernateTemplate包装了 Hibernate 的代码,使用了它以后不能直接访问到Session了,所以我们无法通过 Session 对象得到 Query 了,所以这种情况下我们无法直接使用 Query 来查询。
翻看 HibernateTemplate 提供的 find() 方法源码我们可以看到,其底层通过实现 HibernateCallback 这个接口,而 doInHibernate 方法内的Session 对象是绑定到该线程的 Session 实例,HibernateTemplate 会确保当前的 session 的正确打开和关闭,并直接参与到事务管理中去:
``` java
public List find(final String queryString, final Object... values) throws DataAccessException {
return executeWithNativeSession(new HibernateCallback() {
public List doInHibernate(Session session) throws HibernateException {
Query queryObject = session.createQuery(queryString);
prepareQuery(queryObject);
if (values != null) {
for (int i = 0; i < values.length; i++) {
queryObject.setParameter(i, values[i]);
}
}
return queryObject.list();
}
});
}
```
此接口使得 HibernateTemplate 能更加灵活的操作数据库,在本项目中 [/SimpleCrm/src/page/PageHibernateCallback.java] 便是基于 HibernateCallback 来实现分页功能模板,要使用 HibernateCallback 接口,你可以调用 HibernateTimplate 提供的两个方法进行操作:
``` java
Object execute(HibernateCallback action)
List execute(HibernateCallback action)
```
## 项目路径(作者已经懒得备注了):
```
|---src
|---MyCrmSql.sql
|---cn
|---sqdyy
|---crm
|---hrResourceDepartment
|---service --service层
|---PostService.java
|---StaffService.java
|---DepartmentService.java
|---impl
|---DepartmentServiceImpl.java
|---PostServiceImpl.java
|---StaffServiceImpl.java
|---dao
|---PostDao.java
|---impl
|---StaffDaoImpl.java
|---PostDaoImpl.java
|---DepartmentDaoImpl.java
|---DepartmentDao.java
|---StaffDao.java
|---domain
|---CrmPost.hbm.xml
|---CrmDepartment.hbm.xml
|---CrmStaff.java
|---CrmStaff.hbm.xml
|---CrmDepartment.java
|---CrmPost.java
|---web
|---action
|---PostAction.java
|---StaffAction.java
|---DepartmentAction.java
|---page
|---PageHibernateCallback.java
|---PageBean.java
|---studyManageDepartment
|---service
|---StudentService.java
|---impl
|---StationServiceImpl.java
|---StudentServiceImpl.java
|---RunoffServiceImpl.java
|---RunoffService.java
|---StationService.java
|---dao
|---RunoffDao.java
|---StudentDao.java
|---impl
|---StudentDaoImpl.java
|---RunoffDaoImpl.java
|---StationDaoImpl.java
|---StationDao.java
|---domain
|---CrmRunoff.hbm.xml
|---CrmStudent.hbm.xml
|---CrmStation.hbm.xml
|---CrmRunoff.java
|---CrmStation.java
|---CrmStudent.java
|---web
|---action
|---StudentAction.java
|---StationAction.java
|---RunoffAction.java
|---base
|---BaseAction.java
|---impl
|---BaseDaoImpl.java
|---BaseDao.java
|---utils
|---MyFileUtils.java
|---MyStringUtils.java
|---consultingDepartment
|---service
|---ReferService.java
|---impl
|---ReferServiceImpl.java
|---FollowServiceImpl.java
|---FollowService.java
|---dao
|---FollowDao.java
|---impl
|---ReferDaoImpl.java
|---FollowDaoImpl.java
|---ReferDao.java
|---domain
|---CrmFollow.hbm.xml
|---CrmFollow.java
|---CrmRefer.java
|---CrmRefer.hbm.xml
|---web
|---action
|---FollowAction.java
|---ReferAction.java
|---web
|---action
|---UiAction.java
|---interceptor
|---LoginInterceptor.java
|---teachingDepartment
|---service
|---CourseTypeService.java
|---impl
|---CourseTypeServiceImpl.java
|---ClassesServiceImpl.java
|---ClassesService.java
|---dao
|---ClassesDao.java
|---CourseTypeDao.java
|---impl
|---CourseTypeDaoImpl.java
|---ClassesDaoImpl.java
|---domain
|---CrmCourseType.hbm.xml
|---CrmClasses.java
|---CrmClasses.hbm.xml
|---CrmCourseType.java
|---web
|---action
|---CourseTypeAction.java
|---ClassesAction.java
|---ClassesAction.properties
|---jobDepartment
|---service
|---impl
|---GraduateServiceImpl.java
|---GraduateService.java
|---dao
|---GraduateDao.java
|---impl
|---GraduateDaoImpl.java
|---domain
|---CrmGraduate.java
|---CrmGraduate.hbm.xml
|---web
|---action
|---GraduateAction.java
|---.git
|---Readme.md
|---WebRoot
|---WEB-INF
|---.gitignore
|---pages
|---coursetype
|---listCourse.jsp
|---addOrEditCourse.jsp
|---login.jsp
|---runoff
|---listRunoff.jsp
|---addRunoff.jsp
|---refer
|---editRefer.jsp
|---addStudent.jsp
|---showRefer.jsp
|---addOrEditRefer.jsp
|---addRefer.jsp
|---listRefer.jsp
|---follow
|---addOrEditFollow.jsp
|---department
|---listDepartment.jsp
|---addOrEditDepartment.jsp
|---staff
|---listStaff.jsp
|---editStaff.jsp
|---updPwd.jsp.bak
|---addStaff.jsp
|---register.jsp
|---updPwd.jsp
|---post
|---listPost.jsp
|---addOrEditPost.jsp
|---student
|---showStudent.jsp
|---listStudent.jsp
|---addOrEditStudent.jsp
|---graduate
|---listGraduate.jsp
|---addOrEditGraduate.jsp
|---frame
|---left.jsp
|---control.jsp
|---right.jsp
|---top.jsp
|---left1.jsp
|---left2.jsp
|---error.jsp
|---station
|---listStation.jsp
|---editStation.jsp
|---frame.jsp
|---classesm
|---showClass.jsp
|---uploadClass.jsp
|---getCalssState.jsp
|---listClass.jsp
|---addOrEditClass.jsp
|---web.xml
|---lib
|---classes
|---css
|---index.jsp
|---META-INF
|---js
|---images
|---.project
|---.settings
|---config
|---struts.xml
|---spring
|---applicationContext-refer.xml
|---applicationContext.xml
|---applicationContext-follow.xml
|---applicationContext-runoff.xml
|---applicationContext-post.xml
|---applicationContext-student.xml
|---applicationContext-staff.xml
|---applicationContext-classes.xml
|---applicationContext-graduate.xml
|---applicationContext-department.xml
|---applicationContext-courseType.xml
|---applicationContext-station.xml
|---jdbcInfo.properties
|---strtus
|---struts-station.xml
|---struts-department.xml
|---struts-refer.xml
|---struts-runoff.xml
|---struts-post.xml
|---struts-graduate.xml
|---struts-courseType.xml
|---struts-staff.xml
|---struts-student.xml
|---struts-classes.xml
|---struts-follow.xml
|---log4j.properties
|---resource
|---项目效果.png
|---crm项目数据库关系图.png
|---.classpath
```