Mybatis使用标签
<association> :一的一方配置<association>标签 对应返回值单个实体
<collection>:多的一方配置<collection>:标签 对应返回值集合
根据实体类的定义,如果是属性集合就配置<collection>,如果返回的数据是一个实体的就配置<association >
1. 根据数据库的关系创建实体类
多表查询时,需要一个实体类多个表的数据.那么需要将表与表的关系,也要反应在实体类与实体类之间的关系.
配置一条数据的一方,使用实体类的引用
配置多条数据的一方,使用List集合
地址表
public class Address {
private Integer aid;
private String aname;
private Student student;
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public String getAname() {
return aname;
}
public void setAname(String aname) {
this.aname = aname;
}
public Integer getAid() {
return aid;
}
public void setAid(Integer aid) {
this.aid = aid;
}
}
学生表
public class Student {
private Integer sid;//int(11) not null auto_increment comment '编号',
private Integer aid;//int(11) null default '0',
private String sname;//varchar(50) null default null comment '姓名',
private String sex;//char(3) null default null comment '性别',
private Date birthday;//date null default null comment '生日',
private Integer age;//int(11) null default null comment '年龄',
//假定一个地址对应一个学生,那么这里就配置一个实体类
private Address address;
//多的一方,使用集合
private List<Course> courses;
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public Integer getAid() {
return aid;
}
public void setAid(Integer aid) {
this.aid = aid;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
}
课程表
public class Course {
private Integer cid;//int(11) not null auto_increment comment '科目编号',
private Integer sid;//int(11) null default null comment '学生编号',
private Integer tid;//int(11) null default null comment '教师编号',
private String courseName;//varchar(50) null default null comment '科目名',
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public Integer getTid() {
return tid;
}
public void setTid(Integer tid) {
this.tid = tid;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
}
association标签
接口代码
public interface StudentMapper {
/**
* 查询所有的学生信息,并包括地址信息
* @return
*/
List<Student> findStudentAndAddress();
/**
* 查询所有的学生信息,并包括地址信息
* @return
*/
List<Student> findStudentAndAddress1();
/**
* 查询学生的信息,包括学生选择的课程
* @return
*/
List<Student> findStudentAndCourse();
/**
* 查询多个个表,将数据放在map里面
* @return
*/
List<Map<String,Object>> findStudentAndCourseToMap();
}
映射文件代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<!-- 命名空间,用于指定动态创建的对象返回的映射接口 -->
<mapper namespace="cn.mapper.StudentMapper">
<!-- #查询学生的信息,并且包括学生的学习的课程 -->
<resultMap type="Student" id="studentAndCourseResultMap" autoMapping="true">
<!-- 多的一方使用collection -->
<!--
property:集合的属性名
ofType:集合元素的类型
select:就是指定查询的操作,操作的结果一定要与collection的类型匹配.
column:就是传入到select的ID的字段名
-->
<collection property="courses" column="sid" autoMapping="true" ofType="Course" select="findCourseBySid">
</collection>
</resultMap>
<!-- 创建一个resultMap组合 findStudentAndAddress操作的结果-->
<resultMap type="Student" id="studentAndAddressResultMap" autoMapping="true">
<!-- 如果是多个表组合autoMapping默认是false,如果不想所有字段都写,要显示声明autoMapping="true" -->
<!--
property:指定实体类的属性
column:指定这个实体类属性对应的外键字段名
javaType:指定实体类的类型
autoMapping:表示,如果数据库的字段和属性一样,自动匹配
-->
<association property="address" column="aid" javaType="Address" autoMapping="true">
<id property="aid" column="AID"/>
<result property="aname" column="aname"/>
</association>
</resultMap>
<resultMap type="Student" id="studentAndAddressResultMap1" autoMapping="true">
<!-- 一的一方 -->
<!-- 指定select查询的操作,查询的的结果一定要与property的实体类的字段匹配 -->
<!-- 注意事项,使用select去获得地址表的数据,因为学生表与地址是通过aid来关联的,那么需要指定aid -->
<!-- 一个映射调用另一个映射文件的操作是,使用"命名空间.操作ID" -->
<association property="address" column="aid" autoMapping="true" select="cn.mapper.AddressMapper.findAddressById">
</association>
</resultMap>
<!-- 需求:查询学生表的所有数据,并且包括地址表的记录 -->
<!-- 方案1:将两个表的数据使用一条SQL语句查询出来,然后使用ResultMap组合查询的结果 -->
<!-- 查询多个表数据不要使用resultType,因为resultType只能接收一个表的数据,如果要接收两个以上的表的数据使用resultMap -->
<select resultMap="studentAndAddressResultMap" id="findStudentAndAddress">
select * from student s,address a where s.AID=a.aid
</select>
<!-- 方案2: 先查询Student表的记录,然后在resultMap的子标签association的select属性指定查询的操作,将结果返回到实体类-->
<select resultMap="studentAndAddressResultMap1" id="findStudentAndAddress1">
SELECT * FROM student
</select>
<!-- 查询学生的信息 -->
<select resultMap="studentAndCourseResultMap" id="findStudentAndCourse">
SELECT * FROM student
</select>
<!-- 查询指定学生编号的课程,通过学生的编号,我们知道该学生选择了哪些课程 -->
<select resultType="Course" id="findCourseBySid">
select * from course where sid=#{sid}
</select>
<select resultType="map" id="findStudentAndCourseToMap">
select * from student s,course c where s.SID=c.SID
</select>
</mapper>
测试
public class StudentMapperTest {
@Test
public void findStudentAndAddress(){
SqlSession session = DbUtils.getSession();
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List<Student> students = studentMapper.findStudentAndAddress();
for(Student s:students){
System.out.println("学生姓名:"+s.getSname()+",地址:"+s.getAddress().getAname());
}
}
@Test
public void findStudentAndAddress1(){
SqlSession session = DbUtils.getSession();
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List<Student> students = studentMapper.findStudentAndAddress1();
for(Student s:students){
System.out.println("学生姓名:"+s.getSname()+",地址:"+s.getAddress().getAname());
}
}
@Test
public void findStudentAndCourse(){
SqlSession session = DbUtils.getSession();
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List<Student> students = studentMapper.findStudentAndCourse();
for(Student s:students){
System.out.println("学生姓名:"+s.getSname());
for(Course c:s.getCourses()){
System.out.println("--课程:"+c.getCourseName());
}
}
}
@Test
public void findStudentAndCourseToMap(){
SqlSession session = DbUtils.getSession();
StudentMapper studentMapper = session.getMapper(StudentMapper.class);
List<Map<String, Object>> students = studentMapper.findStudentAndCourseToMap();
for(Map<String, Object> map:students){
//必须跟数据库的字段一致
System.out.print("学生姓名:"+map.get("SNAME")+",");
System.out.println("--课程:"+map.get("COURSE_NAME"));
}
}
}
collection标签的使用
映射文件代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "mybatis-3-mapper.dtd" >
<!-- 命名空间,用于指定动态创建的对象返回的映射接口 -->
<mapper namespace="cn.mapper.StudentMapper">
<!-- #查询学生的信息,并且包括学生的学习的课程 -->
<resultMap type="Student" id="studentAndCourseResultMap" autoMapping="true">
<!-- 多的一方使用collection -->
<!--
property:集合的属性名
ofType:集合元素的类型
select:就是指定查询的操作,操作的结果一定要与collection的类型匹配.
column:就是传入到select的ID的字段名
-->
<collection property="courses" column="sid" autoMapping="true" ofType="Course" select="findCourseBySid">
</collection>
</resultMap>
<!-- 创建一个resultMap组合 findStudentAndAddress操作的结果-->
<resultMap type="Student" id="studentAndAddressResultMap" autoMapping="true">
<!-- 如果是多个表组合autoMapping默认是false,如果不想所有字段都写,要显示声明autoMapping="true" -->
<!--
property:指定实体类的属性
column:指定这个实体类属性对应的外键字段名
javaType:指定实体类的类型
autoMapping:表示,如果数据库的字段和属性一样,自动匹配
-->
<association property="address" column="aid" javaType="Address" autoMapping="true">
<id property="aid" column="AID"/>
<result property="aname" column="aname"/>
</association>
</resultMap>
<resultMap type="Student" id="studentAndAddressResultMap1" autoMapping="true">
<!-- 一的一方 -->
<!-- 指定select查询的操作,查询的的结果一定要与property的实体类的字段匹配 -->
<!-- 注意事项,使用select去获得地址表的数据,因为学生表与地址是通过aid来关联的,那么需要指定aid -->
<!-- 一个映射调用另一个映射文件的操作是,使用"命名空间.操作ID" -->
<association property="address" column="aid" autoMapping="true" select="cn.mapper.AddressMapper.findAddressById">
</association>
</resultMap>
<!-- 需求:查询学生表的所有数据,并且包括地址表的记录 -->
<!-- 方案1:将两个表的数据使用一条SQL语句查询出来,然后使用ResultMap组合查询的结果 -->
<!-- 查询多个表数据不要使用resultType,因为resultType只能接收一个表的数据,如果要接收两个以上的表的数据使用resultMap -->
<select resultMap="studentAndAddressResultMap" id="findStudentAndAddress">
select * from student s,address a where s.AID=a.aid
</select>
<!-- 方案2: 先查询Student表的记录,然后在resultMap的子标签association的select属性指定查询的操作,将结果返回到实体类-->
<select resultMap="studentAndAddressResultMap1" id="findStudentAndAddress1">
SELECT * FROM student
</select>
<!-- 查询学生的信息 -->
<select resultMap="studentAndCourseResultMap" id="findStudentAndCourse">
SELECT * FROM student
</select>
<!-- 查询指定学生编号的课程,通过学生的编号,我们知道该学生选择了哪些课程 -->
<select resultType="Course" id="findCourseBySid">
select * from course where sid=#{sid}
</select>
<select resultType="map" id="findStudentAndCourseToMap">
select * from student s,course c where s.SID=c.SID
</select>
</mapper>