一对多关联关系
说明:在完成了一对一关联测试以后,发现了一个问题,就是上一篇博文中,只是单向的一对一,于是就想怎么样才能改成双向的呢。抱着这个想法开始先看一对多关联映射,然后回过头去看一对一的双向关联映射就直接迎刃而解了。
1.首先,没有重新搭建开发环境,直接在一对一关联的项目中添加多对多关联映射的实例。此处打码后贴出
2.pom.xml
本文件中还是用上一文章中提到的代码就可以了,然后由于开启了延迟加载功能,所以在编译项目的时候,提示我需要添加cglib的支持(也就是少jar包了),添加以下依赖即可。
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
3.mybatis的全局配置文件就不在粘贴,有需要就参考前一篇文章,下面从SQL脚本开始
CREATE TABLE tb_clazz (
id INT PRIMARY KEY AUTO_INCREMENT,
CODE VARCHAR(18),
NAME VARCHAR(18)
);
INSERT INTO tb_clazz(CODE , NAME)
VALUES('j1601','Java就业班');
CREATE TABLE tb_student (
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(18),
sex VARCHAR(18),
age INT,
clazz_id INT,
FOREIGN KEY (clazz_id) REFERENCES tb_clazz(id)
);
INSERT INTO tb_student (NAME,sex,age,clazz_id)
VALUES('jack','男',23,1),
('rose','女',18,1),
('tom','男',21,1),
('alice','女',20,1);
4.实体类:
Clazz.java
public class Clazz implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String code;
private String name;
//一个班级可有多个学生,所以班级和学生是一对多的关系
private List<Student> students;
/**省略set和get方法*/
}
Student.java
public class Student implements Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
private String sex;
private int age;
//学生和班级是多对一的关系,即一个学生只能属于一个班级
private Clazz clazz;
/**省略set和get方法*/
}
5.映射文件(对应的接口略)
ClazzMapper.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.fkit.mapper.ClazzMapper">
<!-- 根据id查询班级信息,返回resultMap -->
<select id="selectClazzById" parameterType="int" resultMap="clazzResultMap">
select * from tb_clazz
where id = #{id}
</select>
<resultMap type="org.fkit.domain.Clazz" id="clazzResultMap">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="name" column="name"/>
<!--
一对多关联映射:collection
fetchType="lazy"表示懒加载 ,使用懒加载时需要在mybatis的全局配置文件中配置相应的信息
select属性表示会使用column属性的id值作为参数执行StudentMapper中定义的selectStudentByClazzId查询班级
对应的所有学生数据,查询出的数据将被封装到property表示的students对象当中
-->
<collection property="students" fetchType="lazy"
javaType="ArrayList" column="id" ofType="org.fkit.domain.Student"
select="org.fkit.mapper.StudentMapper.selectStudentByClazzId">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
</collection>
</resultMap>
</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.fkit.mapper.StudentMapper">
<!-- 根据id查询学生信息,多表连接,返回resultMap -->
<select id="selectStudentById" parameterType="int" resultMap="studentResultMap">
select * from tb_clazz c,tb_student s
where c.id = s.clazz_id and s.id = #{id}
</select>
<!-- 根据班级id查询学生信息,返回resultMap -->
<select id="selectStudentByClazzId" parameterType="int" resultMap="studentResultMap">
select * from tb_student where clazz_id = #{id}
</select>
<!-- 映射Student对象的resultMap -->
<resultMap type="org.fkit.domain.Student" id="studentResultMap">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<!--
多对一关联映射:association
因为<select id="selectStudentById"……/>的SQL语句是一条
多表连接,关联tb_clazz表的同时查询了班级数据,所以以下的association只是
简单的装载数据。
-->
<association property="clazz" javaType="org.fkit.domain.Clazz">
<id property="id" column="id"/>
<result property="code" column="code"/>
<result property="name" column="name"/>
</association>
</resultMap>
</mapper>
6.测试类(注:测试的时候遇到点小问题,就是在测根据id查询Student信息时,不知道为什么获取不到Student的name值,不过这不影响我们学习一对多这个示例)
public class OneToManyTest {
public static void main(String[] args) throws Exception {
// 读取mybatis-config.xml文件
InputStream inputStream = Resources.getResourceAsStream("mybatis/mybatis-config.xml");
// 初始化mybatis,创建SqlSessionFactory类的实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
.build(inputStream);
// 创建Session实例
SqlSession session = sqlSessionFactory.openSession();
OneToManyTest t = new OneToManyTest();
//t.testSelectClazzById(session);
t.testSelectStudentById(session);
// 提交事务
session.commit();
// 关闭Session
session.close();
}
// 测试一对多,查询班级Clazz(一)的时候级联查询学生Student(多)
public void testSelectClazzById(SqlSession session){
// 获得ClazzMapper接口的代理对象
ClazzMapper cm = session.getMapper(ClazzMapper.class);
// 调用selectClazzById方法
Clazz clazz = cm.selectClazzById(1);
// 查看查询到的clazz对象信息
System.out.println(clazz.getId() + " "+ clazz.getCode() + " "+clazz.getName());
// 查看clazz对象关联的学生信息
List<Student> students = clazz.getStudents();
for(Student stu : students){
System.out.println(stu.getName());
}
}
// 测试多对一,查询学生Student(多)的时候级联查询 班级Clazz(一)
public void testSelectStudentById(SqlSession session){
// 获得StudentMapper接口的代理对象
StudentMapper sm = session.getMapper(StudentMapper.class);
// 调用selectStudentById方法
Student stu = sm.selectStudentById(1);
// 查看查询到的Student对象信息
System.out.println(stu);
// 查看Student对象关联的班级信息
System.out.println(stu.getClazz().getName());
}
}