一. 概述:
在实际开发中,对数据库的操作常常会涉及多张表,这在面向对象中就涉及了对象与对象之间的关联关系。针对多表之间的操作,MyBatis框架提供了关联映射,通过关联映射就可以很好地处理对象与对象之间的关联关系。
二.关联关系:
下面我们看两张表,Teacher(教师表)和Teaching(所教课程表)然后这张表里面教师工号(Tno)和所教课程编号(cno)是一对一的关系。
三. 一对一关系:
上面分析的关系我们通过查询教师工号同时能看到教师所教的课程编号,及我们还要在Teacher持久类中添加teaching这个属性。(这是从Teacher角度考虑的)
然后我们来看他们的Mapper.xml配置文件,首先先看到他们的对应接口:
接着我们编写他们的Mapper.xml文件
然后可以按着接口写测试方法了。
代码一:
1.TeacherMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.TeacherMapper">
<select id="findTeacherByTno" parameterType="string" resultMap="classNameByID">
select * from teacher where Tno=#{Tno}
</select>
<resultMap id="classNameByID" type="Teacher">
<id property="Tno" column="Tno"></id>
<result property="Tname" column="Tname"></result>
<result property="Tsex" column="Tsex"></result>
<result property="Tbirthday" column="Tbirthday"></result>
<result property="deptno" column="deptno"></result>
<association property="teaching" column="tno" javaType="Teaching"
select="org.example.mapper.TeachingMapper.findCnameByTno"/>
</resultMap>
</mapper>
2.TeachingMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.TeachingMapper">
<select id="findCnameByTno" parameterType="string" resultType="Teaching">
select * from teaching where tno=#{tno}
</select>
</mapper>
方式二:
代码二:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.TeacherMapper">
<select id="findTeacherByTno" parameterType="string" resultMap="classNameByID">
SELECT * FROM teacher a RIGHT JOIN teaching b on a.Tno=b.tno where a.Tno=#{Tno}
</select>
<!-- <resultMap id="classNameByID" type="Teacher">-->
<!-- <id property="Tno" column="Tno"></id>-->
<!-- <result property="Tname" column="Tname"></result>-->
<!-- <result property="Tsex" column="Tsex"></result>-->
<!-- <result property="Tbirthday" column="Tbirthday"></result>-->
<!-- <result property="deptno" column="deptno"></result>-->
<!-- <association property="teaching" column="tno" javaType="Teaching"-->
<!-- select="org.example.mapper.TeachingMapper.findCnameByTno"/>-->
<!-- </resultMap>-->
<resultMap id="classNameByID" type="Teacher">
<id property="Tno" column="Tno"></id>
<result property="Tname" column="Tname"></result>
<result property="Tsex" column="Tsex"></result>
<result property="Tbirthday" column="Tbirthday"></result>
<result property="deptno" column="deptno"></result>
<association property="teaching" javaType="Teaching">
<id property="cno" column="cno"></id>
<result property="tno" column="tno"></result>
<result property="cterm" column="cterm"></result>
</association>
</resultMap>
</mapper>
三. 一对多关系:
使用association映射到JavaBean的某个“”复杂类型“属性,如JavaBean类,即JavaBean内部嵌套一个复杂数据类型(JavaBean)属性,这种情况就属于复杂类型的关联。但是要注意的是,association元素仅仅处理一对一的关联关系。
比如一个系可能对应多个教师,那我们要实现查询一个系号然后返回属于这个系号的教师名字,这时候我们就要用到一对多的关系了,这时我们就要用到collection来实现了。
在Department持久实体类中添加一个存放Teacher集合的List<Teacher> 属性
TeacherMapper接口中加入方法
List<Teacher> findTeacherBydeptno(String deptno);
TeacherMapper.xml
<select id="findTeacherBydeptno" parameterType="string" resultType="Teacher">
SELECT * FROM teacher WHERE deptno=#{deptno}
</select>
测试:
代码:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.DepartmentMapper">
<select id="findTeachersBydeptno" parameterType="string" resultMap="findteachsResult" >
SELECT * FROM department WHERE deptno=#{deptno}
</select>
<resultMap id="findteachsResult" type="Department">
<id property="deptno" column="deptno"></id>
<result property="deptname" column="deptname"></result>
<result property="deptheader" column="deptheader"></result>
<result property="office" column="office"></result>
<collection property="teachers" column="deptno" ofType="Teacher"
select="org.example.mapper.TeacherMapper.findTeacherBydeptno"/>
</resultMap>
</mapper>
方式二:
四. 多对多:
在实际开发中,多对多的关联关系也是很常见,在学校,一个学生选了多门课,一门课也有很多学生选,这就是多对多的关系。下面我们了解如何实现多对多的关系。
然后先创建两个持久化类Sc和Student
和他们对应的接口:
package org.example.mapper;
import org.apache.ibatis.annotations.Param;
import org.example.po.Student;
import java.util.List;
public interface StudentMapper {
List<Student> getStudent(@Param("cno")String cno);
}
package org.example.service;
import org.apache.ibatis.annotations.Param;
import org.example.po.Sc;
import java.util.List;
public interface ScService {
List<Sc> getSc(String cno);
}
Mapper配置文件:
StudentMapper.xml:
SCMapper.xml:
代码:
ScMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.ScMapper">
<resultMap id="Sclist1" type="Sc">
<id property="sno" column="sno"></id>
<result property="cno" column="cno"></result>
<result property="degree" column="degree"></result>
<collection property="students" ofType="Student" column="cno"
select="org.example.mapper.StudentMapper.getStudent"/>
</resultMap>
<select id="getSc" parameterType="string" resultMap="Sclist1">
select * from sc
<if test="cno!=null and cno!=''">where cno=#{cno}</if>
</select>
</mapper>
StudentMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.mapper.StudentMapper">
<select id="getStudent" resultType="Student" parameterType="string">
SELECT * from student WHERE sno IN (SELECT sno FROM sc WHERE cno=#{cno})
</select>
</mapper>
sevice部分:
package org.example.service;
import org.apache.ibatis.annotations.Param;
import org.example.po.Sc;
import java.util.List;
public interface ScService {
List<Sc> getSc(String cno);
}
package org.example.service;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.example.mapper.ScMapper;
import org.example.po.Sc;
import java.util.List;
public class ScServiceImpl implements ScService{
private SqlSessionFactory sqlSessionFactory;
public ScServiceImpl(SqlSessionFactory sqlSessionFactory){
this.sqlSessionFactory=sqlSessionFactory;
}
@Override
public List<Sc> getSc(String cno) {
SqlSession sqlSession=sqlSessionFactory.openSession();
ScMapper scMapper=sqlSession.getMapper(ScMapper.class);
List<Sc> scs=scMapper.getSc(cno);
sqlSession.close();
return scs;
}
}
测试方法:
package org.example;
import static org.junit.Assert.assertTrue;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.example.mapper.TeacherMapper;
import org.example.po.Department;
import org.example.po.Sc;
import org.example.po.Student;
import org.example.po.Teacher;
import org.example.service.DepartmentServiceImpl;
import org.example.service.ScServiceImpl;
import org.example.service.TeacherServiceImpl;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Unit test for simple App.
*/
public class AppTest
{
private SqlSessionFactory sqlSessionFactory;
@Before
public void init() throws IOException {
InputStream in= Resources.getResourceAsStream("MyBatis_config.xml");
this.sqlSessionFactory=new SqlSessionFactoryBuilder().build(in);
}
// @Test
// public void findTeacherByTno(){
// TeacherServiceImpl teacherService=new TeacherServiceImpl(sqlSessionFactory);
// Teacher teacher=teacherService.findTeacherByTno("601");
// System.out.println(teacher);
// }
// @Test
// public void findteacherDeptno(){
// DepartmentServiceImpl departmentService=new DepartmentServiceImpl(sqlSessionFactory);
// List<Department> department=departmentService.findTeachersBydeptno("d01");
//
// }
@Test
public void getstudent(){
ScServiceImpl scService=new ScServiceImpl(sqlSessionFactory);
List<Sc> scs=scService.getSc(null);
for (Sc sc:scs){
System.out.println("课程编号为"+sc.getCno()+"的课:");
for(Student student:sc.getStudents()){
System.out.println("学生姓名为:"+student.getSname()+"学生班级为:"+student.getClassno());
}
}
}
}