天天看点

Java小白学习MyBatis:实现一对多有几种方式?具体怎么实现?

作者:Java技术汇

在MyBatis中,实现一对多关系有两种方式:基于嵌套查询和基于嵌套结果。

1、基于嵌套查询

以学生成绩表和课程表的关系为例,在学生成绩表中,一个学生可以有多条成绩记录,每一条成绩记录都与某一门课程相关联。而在课程表中,每一门课程也会有多条成绩记录,因此它们之间就是一个典型的一对多关系。

Java小白学习MyBatis:实现一对多有几种方式?具体怎么实现?

我们可以采用嵌套的方式设计SQL语句,先查询学生成绩表,然后再根据课程ID字段查询课程表。具体步骤如下:

1)在Mapper文件中定义查询成绩的方法,同时在ResultMap中定义成绩信息(包括学生ID、学号、姓名、课程ID和成绩)以及嵌套的子查询语句。

<select id="selectScore" resultMap = "scoreResult">
    SELECT s.student_id, s.student_no, s.name, s.course_id, s.score
    FROM score s
</select>

<resultMap id="scoreResult" type="Score">
    <id property="studentId" column="student_id"/>
    <result property="studentNo" column="student_no"/>
    <result property="name" column="name"/>
    <collection property="courses" ofType="Course" resultMap="courseResult"/>
</resultMap>

<resultMap id="courseResult" type="Course">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
</resultMap>
           

2)在Mapper文件中定义查询课程信息的方法,并在ResultMap中定义课程信息。

<select id="selectCourseById" parameterType="Integer" resultMap="courseResult">
    SELECT course_id AS id, name
    FROM course
    WHERE course_id = #{id}
</select>
           

3)在Java代码中调用Mapper中的方法,获取所有学生的成绩列表。

public List<Score> selectAllScores() {
    try(SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession()) {
        return sqlSession.selectList("selectScore");
    }
}
           

4)在返回结果中会得到多条学生成绩记录,每个记录中都包含有关该学生以及他们所属课程的信息。从结果中提取课程ID字段,然后调用查询课程信息的方法来获取相关联的课程详细信息。

public List<Score> selectAllScores() {
    try(SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession()) {
        List<Score> scores = sqlSession.selectList("selectScore");
        for(Score score : scores) {
            Integer courseId = score.getCourseId();
            Course course = sqlSession.selectOne("selectCourseById", courseId);
            score.setCourse(course);
        }
        return scores;
    }
}
           

2、基于嵌套结果

另一种实现一对多关系的方式是基于嵌套结果,它允许我们将子结果映射到父结果中。使用此方法时,先定义含有多个属性的父实体类,然后定义该类与子实体类的关联关系。

以新闻分类和新闻列表为例,在新闻分类表中,每个分类可以包含多篇新闻,因此我们将它们之间的关系建立起来,并使用基于嵌套结果的方式查询。具体步骤如下:

1)在Mapper文件中定义查询新闻分类列表以及各分类下的新闻。在ResultMap中定义新闻分类信息(包括分类ID、分类名称)以及与之对应的所有新闻信息。

<select id="selectCategoryNews" resultMap="newsCategoryResult">
    SELECT c.category_id, c.name, n.news_id, n.title, n.content
    FROM category c LEFT JOIN news n ON c.category_id = n.category_id
    ORDER BY c.category_id, n.news_id
</select>

<resultMap id="newsCategoryResult" type="NewsCategory">
    <id property="categoryId" column="category_id"/>
    <result property="name" column="name"/>
    <collection property="newsList" ofType="News" resultMap="newsResult"/>
</resultMap>

<resultMap id="newsResult" type="News">
    <id property="newsId" column="news_id"/>
    <result property="title" column="title"/>
    <result property="content" column="content"/>
</resultMap>
           

2)在Java代码中调用Mapper中的方法,获取所有新闻分类及其对应的新闻列表。

public List<NewsCategory> selectAllCategoriesWithNews() {
    try(SqlSession sqlSession = MyBatisUtil.getSqlSessionFactory().openSession()) {
        return sqlSession.selectList("selectCategoryNews");
    }
}
           

3)从查询结果中可得到多个新闻分类,它们及它们所属的新闻构成了一个嵌套的列表结构。可以将结果自动映射到含有父实体(NewsCategory)和子实体(News)的Java类中。

这样就完成了对一对多关系的查询。两种方式均可高效地实现一对多关系,并使数据的存取更加灵活。