SSH整合项目_CRM

CRM练习介绍
crm:customer relational manager,客户关系管理

功能模块划分
第一个 客户管理模块
	(1)新增客户功能
	(2)客户列表功能
	(3)修改客户功能
	(4)删除客户功能
	(5)分页列表功能

第二个 联系人管理模块
	(1)新增联系人
	- 选择所属客户
	- 上传文件(struts2实现上传)
	(2)联系人列表
	(3)修改联系人
	(4)级联删除(删除客户,把客户里面所有联系人也删除)
第三个 客户拜访管理模块
	(1)新增客户拜访
	(2)客户拜访列表
	- 解决问题:hibernate多对多配置实现方式

第四个 综合查询模块
	(1)客户条件查询
	- 多条件组合查询
	
第五个 统计分析模块
	(1)根据来源进行统计分析
	- 使用hibernateTemplate调用底层sql

4 练习使用技术:
Struts2 + hibernate5.x + spring4.x + mysql数据库
环境搭建
第一步 导入jar包
 
第二步 搭建struts2环境
(1)创建action,创建struts.xml配置文件,配置action
(2)配置struts2的过滤器

第三步 搭建hibernate环境
(1)创建实体类
(2)配置实体类和数据库表映射关系
(3)创建hibernate核心配置文件
- 引入映射配置文件

第四步 搭建spring环境
(1)创建spring核心配置文件
(2)让spring配置文件在服务器启动时候加载
- 配置监听器
- 指定spring配置文件位置

第五步 struts2和spring整合
(1)把action在spring配置(action多实例的)
(2)在struts.xml中action标签class属性里面写 bean的id值

第六步 spring和hibernate整合
(1)把hibernate核心配置文件中数据库配置,在spring里面配置
(2)把hibernate的sessionFactory在spring配置

第七步 完成互相注入关系(在dao里面使用hibernateTemplate)
(1)在dao注入hibernateTemplate对象 (extends HibernateDaoSupport)
(2)在hibernateTemplate对象中注入sessionFactory

第八步 配置事务

技术点_知识点_

一、Hibernate模板方法

•	Serializable save(Object entity) 
•	 void update(Object entity) 
•	 void delete(Object entity) 
•	 <T> T get(Class<T> entityClass, Serializable id) 
•	 List find(String queryString, Object... values) 

删除、修改的规范写法: 先查询操作,后删除操作。

可使用模型驱动封装得到页面id值

修改时通常根据id值修改信息,则需要将id值作为隐藏输入项,在jsp页面中传向action

删除示例
在这里插入图片描述

二、分页

/**
 * 由于分页操作中,所需数据值较多,所以将数据值统一封装成pageBean.  便于存储,传递。
 *
 *	//在service中完成对pageBean的封装,在dao中使用封装数据进行查询
 * @author 一万年行不行
 *
 */
public class PageBean {
	
	private Integer begin;	//起始位置
	private Integer pageSize;	//每页记录数
	
	private Integer currentPage;  //当前页
	private Integer totalCount;   //总记录数
	private Integer totalPage;	//总页数
	
	private List<Customer> list;	//每页记录集合
}


 pagebean封装过程
	//封装数据到pagebean里面
	public PageBean findPage(Integer currentPage) {
		PageBean pageBean = new PageBean();
		//当前页
		pageBean.setCurrentPage(currentPage);
		
		//总记录数
		//查询数据库得到总记录数
		int totalCount = customerDao.findCount();
		pageBean.setTotalCount(totalCount);
		
		int pageSize = 3;
		//总页数
//		-- 总记录数除以每页显示记录数,
//		如果能够整除,结果是相除结果
//		如果不能整除,结果是相除的结果+1
		int totalPage = 0;
		if(totalCount%pageSize==0) {//整除
			totalPage = totalCount/pageSize;
		} else {
			totalPage = totalCount/pageSize+1;
		}
		pageBean.setTotalPage(totalPage);
		
		//每页查询list集合
		//计算开始位置
		int begin = (currentPage-1)*pageSize;
		List<Customer> list = customerDao.findAllPage(begin,pageSize);
		pageBean.setList(list);
		
		return pageBean;
	}

分页查询两种方式
在这里插入图片描述
JSP页面
在这里插入图片描述

三、条件查询

在这里插入图片描述

四、一对多配置

在这里插入图片描述

五、struts2文件上传

	/** 
	 * 表单页面有要求
		第一个要求:表单提交方式 post
		第二个要求:form标签里面有属性 enctype属性值 修改为 multipart/form-data
		第三个要求:在表单里面有文件上传项,有name属性 <input type= “file” name=“”/>

	 * 
	 * 文件上传:
	 * 步骤1: 文件上传需要定义两个变量  1 文件、 2 文件名
	 * 步骤2:生成get、set方法
	 * 步骤3:具体方法中代码: 
	 * 		1、在创建上传文件地址(服务器端)
	 * 		2、上传文件
	 */
	
	private File upload;   //文件   名称与jsp页面中input文件输入项中name值相同
	private String  uploadFileName;   //文件名:文件+FileName
	public File getUpload() {
		return upload;
	}
	public void setUpload(File upload) {
		this.upload = upload;
	}
	public String getUploadFileName() {
		return uploadFileName;
	}
	public void setUploadFileName(String uploadFileName) {
		this.uploadFileName = uploadFileName;
	}
	
	//添加联系人
	//需要封装表单数据到action中
	public String addLinkMan() throws IOException{
		/**
		 * 可以封装联系人信息,但不能直接封装表单中cid值,因为cid是customer中的属性。
		 * 
		 * 解决:在页面中传入customer.cid   则可将cid传入linkman中的customer属性中 ,则可完成封装
		 */
		System.out.println(linkMan);
		linkManService.addLinkMan(linkMan);
		
		//上传过程  判断是否有文件
		if(upload != null){
			File serverFile = new File("E://sshProjecFileUpload"+"/"+uploadFileName);	//1、在创建上传文件地址(服务器端)
					
			FileUtils.copyFile(upload, serverFile);		//2、上传文件
		}
		return "addLinkMan";
	}

在这里插入图片描述
Jsp页面 上传表单要求
在这里插入图片描述

六、no session问题

在这里插入图片描述
web.xml中过滤器配置
在这里插入图片描述

七、知识点

hibernate外键双向维护
	(1)在客户和联系人这两端都需要维护外键
	(2)解决方式:让其中的一方放弃关系维护(让一那一方放弃)

客户--联系人级联操作
	默认效果:直接删除客户,把联系人外键设置null。
	1)inverse属性值false :表示不放弃
		如果不配置cascade属性值:直接删除客户,把联系人外键设置null。默认效果
			
	2)inverse属性值true:放弃维护。
			1)删除客户时,出现异常。
			2)修改客户时,联系人级联修改
			
	3)cascade值delete:级联删除
	3)inverse属性值true、cascade值delete :级联删除,操作

sql是关系数据库查询语言,面对的数据库;
hql面向对象,hql操作的是持久化类及其属性

八、多对多配置

核心思想:将一个多对多拆分成两个多对一
在这里插入图片描述

实体类创建

public class Visit {
	private Integer visitid;
	private String visitAddress;
	private String visitContent;
	
	//在拜访中表示用户
	private User user = new User();
	
	//在拜访中表示客户
	private Customer customer = new Customer();
	
	public User getUser() {
		return user;
	}
	public void setUser(User user) {
		this.user = user;
	}
	public Customer getCustomer() {
		return customer;
	}
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}
}

在这里插入图片描述

九、BaseDAO抽取

1 定义BaseDAO接口

/**
 * 定义BaseDAO接口
 * @author 一万年行不行
 *
 * @param <T>
 */
public interface BaseDao<T> {
	//添加
	void add(T t);
	
	//删除
	void delete(T t);
	
	//修改
	void update(T t);
	
	//根据id查询
	T findById(int id);
	
	//查询所有
	List<T> findAll();
}

2 BaseDaoImpl接口实现类

/**
 * BaseDaoImpl接口实现类   
 * 继承extends HibernateDaoSupport 
 * @author 一万年行不行
 *
 * @param <T>
 */
public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
	private Class clazzType;
	public BaseDaoImpl() {
		//1 获取当前运行对象的class
		//比如运行customerDao实现类,得到customerDao实现类class
		Class clazz = this.getClass();
		
		//2 获取运行类的父类的参数化类型
		Type type = clazz.getGenericSuperclass();
		
		//3 转换成子接口ParameterizedType
		ParameterizedType ptype = (ParameterizedType) type;
		
		//4 获取实际类型参数
		//比如 Map<key,value>
		Type[] types = ptype.getActualTypeArguments();
		
		//5 把Type变成class
		Class clazzParameter =  (Class) types[0];
		this.clazzType = clazzParameter;
	}

	//根据id查询
	public T findById(int id) {
		return (T) this.getHibernateTemplate().get(clazzType, id);
	}

	//查询所有
	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		
		String className = clazzType.getSimpleName();  //从.class对象中得到为类名  ,查询时需要类名,而不是class对象
		
		return (List<T>) this.getHibernateTemplate().find("from "+className);
	}
		
	//添加
	public void add(T t) {
		this.getHibernateTemplate().save(t);
	}
	//删除
	public void delete(T t) {
		this.getHibernateTemplate().delete(t);
	}
	//修改
	public void update(T t) {
		this.getHibernateTemplate().update(t);
	}
}

3 原接口继承BaseDao接口

/**
 * 原接口继承BaseDao接口
 * 
 * extends BaseDao<Customer>
 * 注释掉原原接口方法 
 * @author 一万年行不行
 *
 */
public interface CustomerDao extends BaseDao<Customer> {

	//	void add(Customer customer);
	//
	//	List<Customer> findAll();
	//
	//  Customer findById(int cid);
	//
	//	void delete(Customer c);
	//
	//	void update(Customer customer);
}

4 原实现类 实现 BaseDAOImpl

/**
 * 原实现类 实现 BaseDAOImpl
 * @author 一万年行不行
 *
 */
public class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao { ... }

十、多条件查询

第一种 写底层hibernate代码实现

第二种 使用hibernate模板里面find方法实现
- 写hql语句实现
	@SuppressWarnings("all")
	public List<Customer> findMoreCondition(Customer customer) {
		//使用hibernate模板里面find方法实现
		//拼接hql语句
		String hql = "from Customer where 1=1 ";
		//创建list集合,如果值不为空,把值设置到list里面
		List<Object> p = new ArrayList<Object>();
		//判断条件值是否为空,如果不为空拼接hql语句
		if(customer.getCustName()!=null && !"".equals(customer.getCustName())) {
			//拼接hql
			hql += " and custName=?";
			//把值设置到list里面
			p.add(customer.getCustName());
		}
		if(customer.getCustLevel()!=null && !"".equals(customer.getCustLevel())) {
			hql += " and custLevel=?";
			p.add(customer.getCustLevel());
		}
		if(customer.getCustSource()!=null && !"".equals(customer.getCustSource())) {
			hql += " and custSource=?";
			p.add(customer.getCustSource());
		}
		System.out.println("hql: "+hql);
		System.out.println("list: "+p);
		return (List<Customer>) this.getHibernateTemplate().find(hql, p.toArray());
	}

第三种 使用离线对象和hibernate模板里面方法
	//使用离线对象方式实现多条件组合查询
	@SuppressWarnings("all")
	public List<Customer> findMoreCondition(Customer customer) {
		
		//创建离线对象,指定对哪个实体类进行操作
		DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
		//判断条件值是否为空
		if(customer.getCustName()!=null && !"".equals(customer.getCustName())) {
			//设置对属性,设置值
			criteria.add(Restrictions.eq("custName", customer.getCustName()));
		}
		if(customer.getCustLevel()!=null && !"".equals(customer.getCustLevel())) {
			criteria.add(Restrictions.eq("custLevel", customer.getCustLevel()));
		}
		if(customer.getCustSource()!=null && !"".equals(customer.getCustSource())) {
			criteria.add(Restrictions.eq("custSource", customer.getCustSource()));
		}
		
		return (List<Customer>) this.getHibernateTemplate().findByCriteria(criteria);
	}

十一、数据字典表

在这里插入图片描述

十二、分组统计

统计效果演示
在这里插入图片描述
sql语句
在这里插入图片描述

分组统计代码

// 联系人级别统计
public List countLinkManLevel() {
	// 复杂语句,需要使用底层sql来实现

	// 1.得到session
	Session session = this.getSessionFactory().getCurrentSession();

	// 2.通过session创建底层SQLQuery,并传入查询语句
	SQLQuery sqlQuery = session.createSQLQuery(
			"SELECT l.num,ll.levelName "+
			"FROM (SELECT COUNT(*) AS num ,lkmLevel FROM t_linkman GROUP BY lkmLevel) l "+
			"inner join t_lkmlevel ll  on l.lkmLevel=ll.levelid");
	/*
	 *  此时查询结果为数组形式,不方便前端页面取值,
	 *  
	 *  可转换为实体类形式,但没有对应实体类 ( sqlQuery.addEntity(类名.class); )
	 *  
	 *  则,转换为map形式
	 */
	//3.将查询结果封装为map
	sqlQuery.setResultTransformer(Transformers.aliasToBean(HashMap.class));
	List list = sqlQuery.list();
	return list;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值