多表关联操作

1. 一对多(客户与订单表)

# 一对多(客户与订单表)
0. C3P0工具类
1. 建domain类与之对应要建立相应的表结构
	Customer表
	private int id;
	private String name;
	private List<Orders> orders = new ArrayList<Orders>();
	Orders表
	private int id;
	private String num;
	private float money;
	private Customer customer;
2. CustomerDaoImpl类
	addCustomer(Customer c)
	Customer findByCustomerId(int i,boolean isDelay) //isDelay是否显示对应的信息
3. 测试类
testAdd()方法
	Customer c = new Customer();
	c.setId(1);
	c.setName("红姐");
	
	Orders o1 = new Orders();
	o1.setId(1);
	o1.setNum("201401");
	o1.setMoney(1000);
	
	Orders o2 = new Orders();
	o2.setId(2);
	o2.setNum("201402");
	o2.setMoney(2000);
	
	//建立关系
testQuery()方法

 

2. 多对多(学生与教师表结构)

# 多对多(学生与教师表结构)
0. C3P0工具类
1. 建domain类与之对应要建立相应的表结构
	学生信息表Student
		private int id;
		private String name;
		private String grade;
		private List<Teacher> teachers = new ArrayList<Teacher>();
	教师信息表
		private int id;// Integer
		private String name;
		private float money;
		private List<Student> students = new ArrayList<Student>();
2. TeacherDaoImpl类		
	void addTeacher(Teacher t1)
		//判断该学生是否存在,?为什么要判断呢,因为如果不判断的话,当添加到第二个老师的时候,学生会再次添加到表中,主键有也约束的
	Teacher findTeacherById(int i)
3. 测试类
addTest()
	Teacher t1= new Teacher();
	t1.setId(1);
	t1.setName("QB");
	t1.setMoney(10000);
	
	Teacher t2= new Teacher();
	t2.setId(2);
	t2.setName("WYJ");
	t2.setMoney(10000);
	
	Student s1 = new Student();
	s1.setId(1);
	s1.setName("DDD");
	s1.setGrade("A");
	
	Student s2 = new Student();
	s2.setId(2);
	s2.setName("DJJ");
	s2.setGrade("A");
testQuery()	

 

分页技术

1. 建domain类与之对应要建立相应的表结构
	create table account (
	  id int primary key,
	  name varchar(20),
	  money float
	);
	insert into account values(1,'aaa',1500);
	insert into account values(2,'bbb',1300);
	insert into account values(3,'ccc',1100);
	insert into account values(4,'ddd',1400);
	insert into account values(5,'eee',13300);
	insert into account values(6,'fff',1100);
	insert into account values(7,'张三',22100);
	insert into account values(8,'小陈',13300);
	insert into account values(9,'阿娇',5500);
	insert into account values(10,'小芙',700);
	insert into account values(11,'丽哥',600);
	insert into account values(12,'ggg',900);
	insert into account values(13,'hhh',800);
	
	------------------------------------------
	或者使用循环语句批量插入数据
	AccountDaoImpl dao = new AccountDaoImpl();
	Account a = new Account();
	Random r = new Random();
	String base = Unicode.getUnicode();
	for(int i=1; i<100; i++) {
		a.setId(i);
		a.setName(base.charAt(r.nextInt(base.length()))+""+base.charAt(r.nextInt(base.length()))+""+base.charAt(r.nextInt(base.length()))+"");
		a.setMoney(10000.00f+i*20);
		dao.updateAccount(a);
	}
	------------------------------------------
	Java类Account
	private int id;
	private String name;
	private float money;
	
2. 数据访问层AccountDaoImpl类
	int getCount()	//获取总记录
	List<Account> getAccountByPage(int startIndex, int size)	//获取每页内容,用作分页查询
	
3. 建立PageBean类
	private int prep;//上一页getPrep
		如果当前页小于1,上一页就等于1;	prep = 1;
		否则上一页等于==当前页-1;		prep = pageNo-1;
	
	private int nextp;//下一页getNextp
		如果下一页大于总页数,下一页就等于总页数		nextp = this.getTotalPage();
		否则就是下一页等于当前页+1 nexp = pageNo+1;
		
	private int totalPage;//总页数-->getTotalPage
		如果总记录数取余每页显示记录数等于0   totalPage=totalRecordes/pageSize
		否则   totalPage=totalRecordes/pageSize+1;

	private int startIndex;//当前页的第一条记录的索引
		(当前页-1)*pageSize--->getStartIndex

	//为了加入滚动数字
	private int endPageno;
	private int beginPageno;
		1. 如果当前页小于9的话,起始页为1,结束页为总页数
		2. 
			否则起始页-4,结束页相应+4
			如果起始页小于0	beginPage=1;
			如果结束页大于总页数	endPageno=this.getTotalPage();
		
	private int pageNo=1;//当前页
	private int pageSize=3;//每页显示的记录数
	
	private int totalRecordes;//总记录数 	
	private List recordes;// 当前页的记录
	
	private String url;
	
4. 业务层AccountServiceImpl类
	void findAccountByPage(PageBean pb)		//进行分页查询
	设置总记录数和当前页的记录	
	
5. ControllerServlet
	1. 乱码问题/生成一个分页组件/获取新的当前页/
	2. 如果当前页不为空并且不等于空,将当前页设置到分页组件中
	3. 调用业务方法,实现分页查询
	4. 设置分页组件中的url
	5. 将分页组件对象设置到request域中
	6. 转发到页面中
	
页面设计
1. index.jsp	<jsp:forward>转发到servlet中
2. list.jsp		在表格中显示数据库中的数据	静态包含page.jsp
3. page.jsp
	1. 当前页/总共页显示	上一页
	2. 滚动数字	遍历每一页 begin/end
	3. 下一页
	4. 选择页(改变事件onchange=changePage(this))
		遍历每一页
		
	changePage(objOpt) {
		地址栏信息提交页去option的value
	}

监听器

1. 自定义监听器

# 自定义观察者模式
1. 定义监听器接口StudentListener
	监听学习方法	void preStudy(StudentEvent event);
	监听吃饭的方法	void preEat(StudentEvent event);
2. 定义事件类StudentEvent
	定义事件源对象/有参构造/getter/setter
3. 事件本身Student学生类
	1. name/监听对象,有参构造
	2. void addStudentListener(StudentListener listener)
	3. void study()	如果监听的对象不为空,执行监听学习方法
	4. void eat()如果监听的对象不为空,执行监听吃饭方法
4. 测试学生类/添加事件源/执行学生中的方法

2. Servlet规范中的8个监听器

感知型
	HttpSessionBindingListenner: 监听自身是否到Httpsession中去了
	HttpSessionActivationListener: 监听自身何时钝化和激活
	
监听器
	事件:
	事件源:
	事件处理程序:
监听三个对象创建和销毁ServletContext/HttpSession/ServletRequest
	ServletContextListener
	HttpSessionListener
	ServletRequestListenner
监听域中数据变化
	ServletContextAttributeListenner
	HttpSessionAttributeListener
	ServletRequestAttributeListener

感知型监听器
	HttpSessionBindingListenner:感知自己何时被HttpSession绑和解绑
	HttpSessionActivationListener:感知自己何时随着HttpSession钝化和激活
	
监听器实现步骤
	1. 写类(实现相应Listenner接口)
	2. 配置web.xml	注册
	<listener>
		<listener-class>全路径名</listener-class>
	</listener>

3. 显示在线用户,并能踢人

1. LoginServlet类
	1.1 解决乱码问题
	1.2 获取登录参数
	1.3 调用业务逻辑,判断用户登录是否成功...
	1.4 创建一个User对象,将登录参数封装进去
	1.5 将user设置到session域中
	1.6 重定向到主页面

2. 使用监听器监听域中的数据,如果有向session域中添加值,这里可以使用监听器类监听到
	所以新建一个UserListener类,实现HttpSessionAttributeListener类,实现其中的方法
	配置web.xml
	
	2.1 首先通过HttpSessionBindingEvent获取到session对象
	2.2 获取session中的user对象
	2.3 如果对象为空直接返回
	2.4 创建User对象
	2.5 判断session中对象是否是User类,如果是 直接将该对象赋值给user
	2.6 如果user对象不等于空
		通过session对象获取ServletContext
		经典代码实现将map设置到context域中(注意map要同步)
		将session对象添加到map集合中

3. 踢出KickServlet类
	3.1 获取username参数
	3.2 将username处理乱码,编码解码
	3.3 得到ServletContext
	3.4 获取context域中的map
	3.5 获取map中的session
	3.6 如果session不等于空,才移除session中的user
	3.7 通过username从集合中移除该用户
	3.8 重定向到首页
		
页面设计
1. login.jsp 提供登录页面,提交到登录LoginServlet
2. index.jsp 主页,如果session中的user不为空,显示在线的用户列表
	因为用户需要在全局显示,所以这里需要将用户列表存在map中,然后遍历集合
	使用<c:url >标签封装地址栏信息,请求参数username,值为,遍历的key
	添加踢人功能链接到url上