1 input处理内容补充
-在struts2里面有错误处理机制,当上传文件超过默认的大小,自动返回结果input
-在struts.xml中配置input的返回结果
<!-- 配置input结果 --> <result name="input">/jsp/error.jsp</result>
(2)当struts2自动返回input结果,出现错误,在配置input的页面中可以查看错误信息
-在配置的错误页面中,使用struts2标签可以查看错误信息
要求使用struts2标签库,添加如下所示:
<s:actionerror/>
客户拜访管理模块
1 什么是客户拜访
(1)客户:与公司有业务往来的
-比如传智播客的客户 有百度、阿里巴巴、新浪
(2)用户:可以使用系统的人
2 用户和客户关系
(1)用户和客户之间是拜访关系
(2)用户和客户是多对多关系
**一个用户可以拜访多个客户,一个客户可以被多个用户拜访
客户:百度、新浪
用户:小王、小宋
*小王 可以 拜访 百度、可以拜访新浪
*百度可以被小王拜访,可以被小宋拜访
(3)多对多建表
-创建第三张表,使用外键维护关系
3 之前在hibernate阶段学过多对多配置
(1)缺陷:第三张表只有两个字段(两个id值)
4 把多对多拆分成两个一对多实现
(1)用户、客户、拜访
(2)用户和拜访是一对多
配置和客户的关系
public class Visit { private Integer vid; private String vaddress;//拜访地址 private String vcontent;//拜访内容
第二步 实体类之间互相表示
(1)用户和拜访一对多
-在用户实体类表示所有拜访记录,使用set集合
//表示所属用户 private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; }
第三步 配置映射关系
(1)一个实体类对应映射文件,创建三个映射文件
<class name="cn.itcast.entity.Visit" table="t_visit"> <id name="vid" column="vid"> <generator class="native"> </generator> </id> <property name="vaddress" column="vaddress"></property> <property name="vcontent" column="vcontent"></property> </class>
(2)用户和拜访一对多
-在用户映射文件中表示所有拜访记录,使用set标签
(3)客户和拜访一对多
-客户映射文件表示所有拜访
<!-- 表示所有拜访记录 --> <set name="setCustVisit"> <key column="cvid"></key> <one-to-many class="cn.itcast.entity.Visit"/> </set>
-在拜访映射文件中表示所属客户
<!-- 拜访记录所属客户 --> <many-to-one name="customer" class="cn.itcast.entity.Customer" column="cvid"></many-to-one>
第四步 把映射文件引入到核心配置文件中
数据库的建表语句如下所示:
CREATE TABLE `t_visit` ( `vid` int(11) NOT NULL AUTO_INCREMENT, `vaddress` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, `vcontent` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, `uvid` int(11) DEFAULT NULL, `cvid` int(11) DEFAULT NULL, PRIMARY KEY (`vid`), KEY `FKneag8njjijyk0mt952k3leyiu` (`uvid`), KEY `FKfq1vs5t876wufr6l5tctnopps` (`cvid`), CONSTRAINT `FKfq1vs5t876wufr6l5tctnopps` FOREIGN KEY (`cvid`) REFERENCES `t_customer` (`cid`), CONSTRAINT `FKneag8njjijyk0mt952k3leyiu` FOREIGN KEY (`uvid`) REFERENCES `t_customer` (`cid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
新增客户拜访
1 点击超链接,到新增用户拜访页面中,
(1)有两个下拉框,选择用户,选择客户
在写完之后一定不要忘记写注解。
客户拜访列表
1 查询拜访列表所有记录(类似于联系人列表)
(1)不显示id值,显示id对应名称
2 核心代码
<c:forEach items="${list }" var="visit"> <TR style="FONT-WEIGHT: normal; FONT-STYLE: normal; BACKGROUND-COLOR: white; TEXT-DECORATION: none"> <TD>${visit.user.username }</TD> <TD>${visit.customer.custName }</TD> <TD>${visit.vaddress}</TD> <TD>${visit.vcontent }</TD> </TR> </c:forEach>
3 有 no session问题
抽取BaseDao
Code Review
系统的概念实现了,但是可能会比较乱,难于维护。
有他人审查代码,并提出解决方案。
1 代码review
2 抽取basedao代码重构方式
(1)在dao层,做操作最基本crud操作
(2)做crud操作时,调用hibernate模板的方法都一样
(3)不同的是参数不同
比如操作客户,传递客户对象,比如操作联系人,传递联系人对象
(4)抽取basedao,减少dao层大量重复的代码。
3 使用反射+泛型实现抽取
(1)反射得到类的class文件内容
-得到类Class方式
-Class.forName()
-类名.class
-对象.getClass()
this.getClass()
得到当前运行的类信息
-getClass()是Object的方法
(2)泛型术语
List<User>
-<>:读成typeof
-List<User>:整体部分读成 参数化类型
-<User>:<>中的User:读成 实际类型参数
具体实现
1 创建basedao接口,使用泛型方式
在接口里面定义操作的方法crud方法
public interface BaseDao<T> { //添加 void add(T t); //修改 void update(T t); //删除 void delete(T t); //根据id查询 T findOne(int id); //查询所有 List<T> findAll(); }
2 创建BaseDao接口实现类
import org.springframework.orm.hibernate5.support.HibernateDaoSupport; public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> { //添加 public void add(T t) { this.getHibernateTemplate().save(t); } //修改 public void update(T t) { this.getHibernateTemplate().update(t); } //删除 public void delete(T t) { this.getHibernateTemplate().delete(t); } //根据id查询 public T findOne(int id) { //不能写T.class //this.getHibernateTemplate().get(T.class, id); return null; } @Override public List<T> findAll() { //this.getHibernateTemplate().find("from"+T); return null; } }
3 在真正功能的接口,继承basedao接口
public interface CustomerDao extends BaseDao<Customer>{
(1)把实现crud操作的方法去掉
/*public void add(Customer customer); public List<Customer> findAll(); public Customer findOne(int cid); public void delete(Customer c); public void update(Customer customer);*/
4 让真正功能的实现类继承BaseDao实现类
(1)在真正的实现类,不需要继承hibernateDaoSupport
public class CustomerDaoImpl extends BaseDaoImpl<Customer> implements CustomerDao {
5 上面操作实现基本概念,有两个查询没有实现
(1)根据id查询,返回对象
(2)查询所有
6 当customerdaoImpl实现类创建对象,父类的构造执行
public class CustomerDaoImpl extends BaseDaoImpl<Customer>
(1)在BaseDaoImpl的构造方法中得到传递对象的class
(2)得到BaseDaoImpl泛型里面Customer的class
7 具体实现
代码实现
private Class pClass; //构造方法 public BaseDaoImpl(){ //第一步 得到当前运行的Class Class clazz = this.getClass(); System.out.println("****************************"+clazz); //第二步 得到运行类的 父类的参数化类型BaseDaoImpl<Customer> //Type getGenericInterfaces() Type type = clazz.getGenericSuperclass(); //使用Type子接口ParameterizedType ParameterizedType ptype = (ParameterizedType)type; //得到的ptype是BaseDaoImpl<Customer>这个整体部分 System.out.println("*****************************"+ptype); //第三步 得到实际类型参数<Customer>里面的Customer //Type[] getActualTypeArguments() //为什么返回的是数据,可能是map Type[] types = ptype.getActualTypeArguments(); //Type接口实现类Class Class tclass = (Class)types[0]; System.out.println("########################"+tclass); this.pClass = tclass; } //根据id查询 @SuppressWarnings("all") public T findOne(int id) { //不能写T.class //this.getHibernateTemplate().get(T.class, id); return (T) this.getHibernateTemplate().get(pClass, id); } @SuppressWarnings("all") public List<T> findAll() { //this.getHibernateTemplate().find("from"+T); //使用Class里面getSimpleName()得到类名称 return (List<T>) this.getHibernateTemplate().find("from "+pClass.getSimpleName()); //这里要加空格 } //添加 public void add(T t) { this.getHibernateTemplate().save(t); } //修改 public void update(T t) { this.getHibernateTemplate().update(t); } //删除 public void delete(T t) { this.getHibernateTemplate().delete(t); }
多条件组合查询
第一种 写底层hibernate代码实现
第二种 使用hibernate模板里面find方法实现
-写hql语句实现
//多条件组合查询 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语句时要加空格,不然是错的 hql += " and custName=?"; //把值设置到List里面 p.add(customer.getCustName()); } if(customer.getCustLevel()!=null && !"".contentEquals(customer.getCustLevel())){ hql += " and custLevel=?"; p.add(customer.getCustLevel()); } if(customer.getCustSource()!=null && !"".contentEquals(customer.getCustSource())){ hql += " and custSource=?"; p.add(customer.getCustSource()); } return (List<Customer>) this.getHibernateTemplate().find(hql, p.toArray()); }
第三种 使用离线对象和Hibernate模板里面方法