MyBatis -- 结果集映射

结果集映射,顾名思义跟结果集有关。无非就是把SQL的查询结果映射到JavaBean的字段上。

一。字段映射
比如有张数据表结构如下:

在后台的JavaBean中,如果遵守规范的话,属性名和列名一致,那么我们就不需要手动做字段映射,MyBatis会自动帮我们把值填充到Bean中。但现在情况不一样,Bean的属性名和数据库列名对应不上。
import java.util.ArrayList;

import java.util.List;

public class Grade {

    private String gradeId;        // 班级ID
    private String gName;        // 班级名
    private List<Student> stuList = new ArrayList<Student>(); // 班级中的学生

    public String getGradeId() {
            return gradeId;
    }


    public void setGradeId(String gradeId) {
            this.gradeId = gradeId;
    }


    public String getgName() {
            return gName;
    }


    public void setgName(String gName) {
            this.gName = gName;
    }


    public List<Student> getStuList() {
            return stuList;
    }


    public void setStuList(List<Student> stuList) {
            this.stuList = stuList;
    }

    @Override
    public String toString() {
            return "Grade [gradeId=" + gradeId + ", gName=" + gName + ", stuList="
                            + stuList + "]";
    }
}
gradeId和GID明显对应不上,但是修改列或者属性名是不可取的,原因不多说。我们可以通过MyBatis的字段映射在不修改代码的情况下完成这个需求,给它俩建立一种映射关系:
字段映射,当数据库的列名和类的属性名不一致时,需要通过建立映射关系使得它俩对应上。

返回的结果都是grade(自己取的typeAliases),只是多了一层映射关系。

<resultMap type="grade" id="mappingGid">
        <!-- 主键列用id标签 -->
        <id property="gradeId" column="GID"/>
<!--                 
        非主键就用result:                
        <result property="gName" column="gname"/>         -
->
</resultMap>

<select id="queryAll" resultType="grade" resultMap="mappingGid">
        select * from grade
</select>
 restltMap属性指向上边定义的resultMap的id即可。resultMap标签还有个autoMapping属性,意思是自动映射,默认值是true,改成false的话就要手动指定需要建立映射关系的列以及属性了。


二。多对一(many to one) 映射

表关系:

grade表:GID、GNAME
student表:SID、SNAME、GID
GID是关联grade表的外键。

多对一的视角:student --> grade。多个学生对应一个grade,一个学生只能有一个grade。

在设计Bean的时候,应该是这样的:
public class Student {


    private String sId;
    private String sName;
    private Grade grade;


    public String getsId() {
            return sId;
    }


    public void setsId(String sId) {
            this.sId = sId;
    }


    public String getsName() {
            return sName;
    }


    public void setsName(String sName) {
            this.sName = sName;
    }

    public Grade getGrade() {
            return grade;
    }


    public void setGrade(Grade grade) {

            this.grade = grade;

    }


    @Override
    public String toString() {
            return "Student [sId=" + sId + ", sName=" + sName + ", grade=" + grade
                            + "]";
    }

}
包含一个grade属性,在查询到学生信息的同时把对应的班级查出来并填充进去。当然用Java代码编写逻辑也是完全能够实现的,但是有了MyBatis的结果集映射,我们并不需要编写这样的逻辑。确定好是一对多关系后,在映射文件中声明映射关系。下面就把这个例子的代码都贴上来吧:

Student映射接口:
import java.util.List;
import cn.et.lesson03.entity.Student;
public interface StudentMapper {
    <!-- 映射多对一关系 -->

    <resultMap type="student" id="mappingGrade">

            <association property="grade" column="gid" select="cn.et.lesson03.xml.GradeMapper.queryGradeByGid"></association>

    </resultMap>

/* 根据ID查询学生 */ public Student queryStuById(String sId); /*根据班级ID查询学生*/ public List<Student> queryStusByGId(String gId);}
现在要调用queryStuById,返回一个student的同时,把这个student的grade属性填充进去,也就是说还需要一个 select * from grade where gid = x 这么一条SQL语句,定义在grade类对应的映射文件中:

    <select id="queryGradeByGid" resultType="grade">

            select * from grade where GID = #{gid}

    </select>
然后在Student类的映射文件中建立映射关系:
    <!-- 映射多对一关系 -->

    <resultMap type="student" id="mappingGrade">

            <association property="grade" column="gid" select="cn.et.lesson03.xml.GradeMapper.queryGradeByGid"></association>

    </resultMap>
 type = 查询返回结果
 id = 映射命名
association = 声明是多对一映射。
property="grade" 需要填充的属性
column="gid" 外键列
select获取对应的grade数据行的SQL语句,上上边那个,语法格式:命名空间.声明。

 映射接口中方法的SQL语句:
    <select id="queryStuById" resultType="student" resultMap="mappingGrade">

            select * from student where SID = #{0}

    </select>
 测试方法:
@Test

    public void mappingGrade() throws IOException{

            SqlSession session = getSession();
            StudentMapper mapper = session.getMapper(StudentMapper.class);
            Student student = mapper.queryStuById("1");
            System.out.println(student.getGrade());
}
结果:

流程:
    调用方法 --> 执行接口映射方法之前先执行resultMap --> 
    通过association中的column外键,执行association对应的SQL语句获取结果集,填充到
    property --> resultMap结束 --> 执行方法对应的SQL语句返回最终结果。

三。一对多映射(one to many)

一对多映射很简单,一个班级对应多个学生,查询一个班级的同时获取班级中的所有学生,填充到stuList属性中:

把上面的例子反过来想就OK了。班级和学生在数据库中的关系是主外键关联,通过grade表的主键到student表查询,需要一个这个的语句:select * from student where GID = #{gid}。

这个语句在Student的映射文件中定义:
    <select id="queryStusByGId" resultType="student">

            select * from student where GID = #{gid}

    </select>

然后在Grade的映射文件中,定义结果集映射:
    <resultMap type="grade" id="mappingStuList">

            <collection property="stuList" javaType="arraylist" column="gid" select="cn.et.lesson03.xml.StudentMapper.queryStusByGId"></collection>

    </resultMap>
一对多关系用collection表示。
property = 要填充的属性
javaType = 该属性的数据类型
column = 主键,studen表的外键
select = student映射文件中的语句: select * from student where GID = #{gid}


测试方法:
    @Testpublic void queryStu() throws IOException {

            SqlSession session = getSession();

            GradeMapper mapper = session.getMapper(GradeMapper.class);

            Grade grade = mapper.queryGradeById("1");

            

            List<Student> list = grade.getStuList();

            for (Student student : list) {

                    System.out.println(student.getsId() + "---" + student.getsName());

            }

    }

运行结果:




四。基于注解实现的结果集映射

字段映射:
    @Results({

    @Result(column="SID" , property = "stuId" , id = true)})

    @Select("select * from student where sid = #{sId}")

    public Student queryStuById(String sId);
多对一映射:
    @Results({

                    @Result(column = "SID", property = "stuId", id = true),

                    @Result(property = "grade", column = "GID", 

                    one = @One(select = "cn.et.lesson03.anno.GradeMapper.queryGradeById")) })

    @Select("select * from student where sid = #{sId}")

    public Student queryStuById(@Param("sId") String sId);
one表示多对一映射,多个学生属于一个grade,指向的方法也是一个grade:
 @Select("select * from grade where GID = #{0}")

    public Grade queryGradeById(String gId);
一对多映射:
指向的方法返回值是个list,所以还要在映射声明中指定一下javaType。
   
@Results({ 
    @Result(column = "GID", property = "stuList", javaType = ArrayList.class, 
     many = @Many(select = "cn.et.lesson03.anno.StudentMapper.queryStusByGId")) })

    @Select("select * from grade where GID = #{0}")

    public Grade queryGradeById(String gId);
一对多用many表示,因为查询结果是多条,指向方法:
    @Results({

    @Result(column = "SID" , property = "stuId")})

    @Select("select * from student where GID = #{param1}")

    public List<Student> queryStusByGId(String gId);






阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36311372/article/details/79089730
个人分类: MyBatis
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭