1、SpringMVC与MyBatis企业开发实战第十一章 MyBatis框架-高级使用实体之间的关联映射q 数据库实体间有三种对应关系:一对一,一对多,多对多。q 一对一关系:一个学生对应一个学生档案。q 一对多关系:一个员工只属于一个部门,但是一个部门有多名员工。q 多对多关系:一个订单中可以包含多件商品,而一件商品也可以出现在多个订单中。一对多的关系实体类package org.newboy.entity;import java.sql.Date;/*员工实体类*author NewBoy*/public class Employee private int id;/编号private St
2、ring name;/姓名private boolean gender;/性别private Date birthday;/生日,使用的是java.sql.Dateprivate Depart depart;/所在部门对象,指定多对一的关联对象Overridepublic String toString()return Employee id=+id+,name=+name+,gender=+gender+,birthday=+birthday+;/省略了getter和setter方法部门的映射配置文件 select*from depart where depart_id=#departId
3、员工的实体配置文件 select*from employee where depart_id=#departId 测试类/*查询某个部门的所有员工,同时输出部门的名字*/Testpublic void testFindEmployees()/第1个参数:指定映射文件中的命名空间和查询id,第2个参数是部门的idList list=sqlSession.selectList(org.newboy.dao.EmployeeDao.selectEmployees,1);for(Employee employee:list)System.out.println(姓名:+employee.getName
4、()+,生日:+employee.getBirthday()+,部门名:+employee.getDepart().getDepartName();一方的配置q 查询所有的部门信息,并且通过关联得到这个部门下所有的员工,一个部门对象中包含一组员工的集合public class Depart private int departId;private String departName;private String description;private List employees;public List getEmployees()return employees;public void se
5、tEmployees(List employees)this.employees=employees;/省略getter/setter方法配置文件select*from depart where depart_id=#departId select*from depart测试类Testpublic void testFindDeparts()List list=sqlSession.selectList(org.newboy.dao.DepartDao.selectAllDeparts);for(Depart depart:list)System.out.println(部门名:+depart
6、.getDepartName();System.out.println(-);/得到这个部门下所有的员工List employees=depart.getEmployees();for(Employee employee:employees)System.out.println(employee);多对多的关系实体类public class Student private int id;private String stuName;/姓名private Set courses;/所选课程集合Overridepublic String toString()return Student id=+i
7、d+,stuName=+stuName+,courses=+courses+;/省略getter和setter方法public class Course private int id;private String courseName;/课程名private Set students;/选择这门课程的学生集合Overridepublic String toString()return Course id=+id+,courseName=+courseName+,students=+students+;/省略getter和setter方法学生映射文件 select*from student wh
8、ere id=#id select s.*from student s inner join student_course sc inner join course c on s.id=sc.student_id and c.id=sc.course_id where c.id=#id;课程映射文件 select c.*from student s inner join student_course sc inner join course c on s.id=sc.student_id and c.id=sc.course_id where s.id=#id select*from cour
9、se where id=#id 测试类/*查询指定学生所学的课程 */Test public void testFindStudent()/得到1号学生 Student s1=sqlSession.selectOne(org.newboy.dao.StudentDao.findStudentById,1);System.out.println(学生:+s1.getStuName();System.out.println(课程:);/输出1号学生所学的课程 Set courses1=s1.getCourses();for(Course course:courses1)System.out.pri
10、ntln(course.getCourseName();/得到2号学生 Student s2=sqlSession.selectOne(org.newboy.dao.StudentDao.findStudentById,2);System.out.println(学生:+s2.getStuName();System.out.println(课程:);/输出2号学生所学的课程 Set courses2=s2.getCourses();for(Course course:courses2)System.out.println(course.getCourseName();/*查询学习某门课程的学生
11、有哪些 */Test public void testFindCourse()/查询1号课程 Course course=sqlSession.selectOne(org.newboy.dao.CourseDao.findCourseById,1);System.out.println(课程名:+course.getCourseName();System.out.println(学习这门课程的学生:);/得到学习这门课程的学生 Set students=course.getStudents();for(Student student:students)System.out.println(st
12、udent.getStuName();延迟加载q 如果后期没有访问员工的属性,部门对象加载员工这个集合属性是没有含义的,这对数据库的查询性能来说也是不划算的。不但多出一些没用的查询语句,还会增加数据库服务器的工作量,如果通过网络传输这些数据的话也会增加网络的带宽占用。所以可以使用延迟加载,当查询部门的时候如果只查询部门的信息,没有访问员工的属性,则不会加载员工的集合。只有访问员工属性employees的时候才再次发送一条SQL语句查询出员工对象的集合这就是延迟加载。核心配置文件Testpublic void testFindDepart()Depart depart=sqlSession.se
13、lectOne(org.newboy.dao.DepartDao.selectDepart,1);System.out.println(部门名:+depart.getDepartName();/得到这个部门下所有的员工List employees=depart.getEmployees();for(Employee employee:employees)System.out.println(员工名:+employee.getName();查询缓存q 默认情况下,mybatis每次向数据库请求查询数据,每次都会向数据库发送SQL语句进行查询。在实际应用中有些相同的查询,即查询条件相同、查询结果相
14、同的情况下,不需要每次都发送SQL语句给数据库,只需第1次查询的时候发送SQL语句给数据库服务器返,之后就可以将查询出来的结果缓存在数据库的服务器内存中。下次如果遇到相同的查询语句,则直接从服务器缓存中将查询结果发送给客户端,不需要每次都查询数据库。这样可以提升查询效率,尤其是多个用户访问相同SQL的时候,可以减少数据库的查询次数。未使用缓存/程序入口public static void main(String args)throws IOException TestCache testCache=new TestCache();System.out.println(-第1次查询-);/第1次
15、查询部门 testCache.findDepart();System.out.println(-第2次查询-);/第2次查询部门,与第1次查询不是同一个会话对象 testCache.findDepart();/*查询1个部门*/public void findDepart()/每次得到不同的会话对象 SqlSession sqlSession=getSqlSession();/查询得到1号部门 Depart depart=sqlSession.selectOne(org.newboy.dao.DepartDao.selectDepart,1);System.out.println(部门名:+d
16、epart.getDepartName();/得到这个部门下所有的员工 List employees=depart.getEmployees();for(Employee employee:employees)/输出员工的名字 System.out.println(员工名:+employee.getName();/提交事务 sqlSmit();/关闭会话 sqlSession.close();使用查询缓存部门的配置文件select*from depart where depart_id=#departId select*from customer and name like concat(%,
17、#name,%)and gender=#gender and age>=#min and age<=#max 测试类/*根据条件查询客户*/Testpublic void testFindByCondition()/创建封装条件的JavaBean Condition condition=new Condition();/没有查询条件,相当于得到所有的记录 List customers=sqlSession.selectList(org.newboy.dao.CustomerDao.findByCondition,condition);for(Customer customer:cu
18、stomers)System.out.println(customer);/封装1个查询条件:性别为女 condition.setGender(女);customers=sqlSession.selectList(org.newboy.dao.CustomerDao.findByCondition,condition);for(Customer customer:customers)System.out.println(customer);/再加多一个条件,年龄为30岁以上的(含)condition.setMin(30);customers=sqlSession.selectList(org.
19、newboy.dao.CustomerDao.findByCondition,condition);for(Customer customer:customers)System.out.println(customer);/再加多一个条件,年龄在40以下的(含)condition.setMax(40);customers=sqlSession.selectList(org.newboy.dao.CustomerDao.findByCondition,condition);for(Customer customer:customers)System.out.println(customer);/
20、再加多一个条件,名字包含天字的 condition.setName(天);customers=sqlSession.selectList(org.newboy.dao.CustomerDao.findByCondition,condition);for(Customer customer:customers)System.out.println(customer);标签 select*from customer and name like concat(%,#name,%)and gender=#gender and id=#id 标签 delete from customer where i
21、d in#id insert into customer(name,gender,age,title,phone,email)values (#c.name,#c.gender,#c.age,#c.title,#c.phone,#c.email)和标签 and name like concat(%,#condition.name,%)and gender=#condition.gender and age>=#condition.min and age<=#condition.max include引用select count(id)from customer select*from customer limit#pageIndex,#pageSize本章总结q 本章我们学习了mybatis中不少高级特性,首先学习了实体类之间的关联映射:一对多和多对多的映射。接着我们学习如何在mybatis中进行性能的优化,讲解了延迟加载和查询缓存两种技术来提升mybatis的性能。最后学习了mybatis中的动态SQL标签的用法。通过本章的学习我们已经可以比较熟练的使用mybatis,后面的章节将会进一步介绍如何整合Spring。