MyBatis 是一款优秀的 ORM 框架,提供给我们了一些关系映射的解决方案。其中比较常见的一对多和多对一的关系映射,我们可以通过 MyBatis 提供的标签和注解来实现。
一对多关系映射
一对多关系通常是指一个实体类关联多个实体类的情况,例如一个学院对应多个专业,一个专业对应多个学生。在 MyBatis 中,我们可以通过使用 Collection 和 Association 标签来实现一对多的关系映射。
使用 Collection 标签
我们假设有一个学院表和一个专业表,一个学院对应多个专业,那么我们的实体类设计可以如下:
public class College {
private Integer id;
private String name;
private List<Major> majors;
// getter、setter
}
public class Major {
private Integer id;
private String name;
private Integer collegeId;
// getter、setter
}
我们需要在 CollegeMapper.xml 中编写返回类型为 College 的 select 语句,用于查询学院和其下的所有专业。我们可以在 College 对象中添加一个 List 类型的属性 majors 来封装查询结果,使用 Collection 标签来实现:
<select id="findCollegeWithMajors" resultType="College">
SELECT c.id, c.name,
m.id AS `majors.id`,
m.name AS `majors.name`,
m.college_id AS `majors.collegeId`
FROM college c
LEFT JOIN major m ON c.id = m.college_id
WHERE c.id = #{id}
ORDER BY m.id
</select>
上述 SQL 语句中使用了别名语法来将 select 查询结果中的 majors.id、majors.name 和 majors.college_id 映射到 Major 对象的属性中。在查询结果集中,按照 Major 的 id 升序排序。
接下来,我们在 CollegeMapper 接口中添加一个方法来调用上述查询语句:
public interface CollegeMapper {
College findCollegeWithMajors(Integer id);
}
最后,在使用 CollegeMapper 接口的地方就可以调用此方法查询学院和其下的专业:
College college = collegeMapper.findCollegeWithMajors(1);
使用 Association 标签
在有些情况下,我们需要将一对多的关联对象作为一个单一的属性进行封装,如将所有专业封装到一个字符串中。此时,我们可以使用 Association 标签来实现。
使用 Association 标签时,我们需要定义一个实体类来封装关联对象的多个属性。假设我们需要将一个学院下的所有专业名封装到一个字符串中,我们需要先新建一个封装类:
public class CollegeWithMajorNames {
private Integer id;
private String name;
private String majorNames; // 专业名,以逗号分隔
// getter、setter
}
然后在 CollegeMapper.xml 中编写返回类型为 CollegeWithMajorNames 的 select 语句:
<select id="findCollegeWithMajorNames" resultType="CollegeWithMajorNames">
SELECT c.id, c.name,
GROUP_CONCAT(m.name SEPARATOR ',') AS `majorNames`
FROM college c
LEFT JOIN major m ON c.id = m.college_id
WHERE c.id = #{id}
GROUP BY c.id
</select>
上述 SQL 语句使用了 MySQL 的 GROUP_CONCAT 函数将多条查询结果合并为一个字符串,使用逗号作为分隔符。在查询结果集中,仅有一个 CollegeWithMajorNames 对象。
最后,我们在 CollegeMapper 接口中添加一个方法来调用上述查询语句:
public interface CollegeMapper {
CollegeWithMajorNames findCollegeWithMajorNames(Integer id);
}
最终,在使用 CollegeMapper 接口的地方就可以调用此方法查询学院和其下的专业名:
CollegeWithMajorNames collegeWithMajorNames = collegeMapper.findCollegeWithMajorNames(1);
多对一关系映射
多对一关系通常是指多个实体类关联一个实体类的情况,例如多个学生对应一个专业,多个专业对应一个学院。在 MyBatis 中,我们可以通过使用 ResultMap 标签和对应实体类的关联属性来实现多对一的关系映射。
假设一个学生表和一个专业表,一个学生对应一个专业,一个专业对应一个学院,那么我们的实体类设计可以如下:
public class Student {
private Integer id;
private String name;
private Integer majorId;
// getter、setter
}
public class Major {
private Integer id;
private String name;
private Integer collegeId;
// getter、setter
}
public class College {
private Integer id;
private String name;
// getter、setter
}
我们需要在 StudentMapper.xml 中编写返回类型为 Student 的 select 语句,用于查询学生和其所属的专业和学院。我们可以在 Student 对象中添加一个 Major 类型的属性 major 和一个关联属性 college,分别表示学生所属的专业和所属的学院。使用 ResultMap 标签和对应实体类的关联属性来实现多对一的关系映射:
<resultMap id="studentResultMap" type="Student">
<id column="id" property="id"/>
<result column="name" property="name"/>
<association property="major" column="major_id" javaType="Major" select="findMajorById"/>
<association property="college" javaType="College">
<id column="college_id" property="id"/>
<result column="college_name" property="name"/>
</association>
</resultMap>
<select id="findStudentWithMajorAndCollege" resultMap="studentResultMap">
SELECT s.id, s.name,
s.major_id,
m.college_id,
m.name AS `major.name`,
c.id AS `college.id`,
c.name AS `college_name`
FROM student s
JOIN major m ON s.major_id = m.id
JOIN college c ON m.college_id = c.id
WHERE s.id = #{id}
</select>
<select id="findMajorById" resultType="Major">
SELECT id, name, college_id FROM major WHERE id = #{id}
</select>
上述 SQL 语句中,我们需要先定义一个 ResultMap 标签,并使用 association 标签来表示关联属性。在 association 标签中使用 id 标签表示关联对象的主键,使用 result 标签来将查询结果中的列映射到关联对象的属性中。在第二个 association 标签中,我们将 Java 类型指定为 College,表示既然已经查询过 Major 的信息,也就同时查询了 College 的信息,可以将其封装到一个新的对象中。
接下来,我们在 StudentMapper 接口中添加一个方法来调用上述查询语句:
public interface StudentMapper {
Student findStudentWithMajorAndCollege(Integer id);
}
最后,在使用 StudentMapper 接口的地方就可以调用此方法查询学生和其所属的专业和学院:
Student student = studentMapper.findStudentWithMajorAndCollege(1);
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:mybatis关系映射之一对多和多对一 - Python技术站