深入浅出Mybatis原理中一对一级联最严重的一个错误!!

先分析表的关系:

首先主表是学生课程表
然后副表是课程表
两个表之间是一对一的关系(主表的一条记录只对应副表的一条记录)
现在该干什么?从哪里开始啊?
现在要做的事情是要把副表的信息整合到主表中来
这里先放一问题再这里:
为什么要把副表的信息整合到主表中来啊?
很明显,从主表学生课程表那里获得信息是不完整的
这里从头再来捋一捋:
问题的源头是:
我们对学生课程表的查询出现了问题
来看一下是怎么回事:
先分析学生课程表:
学生课程表中的一条记录代表某一名学生在某一课程上的分数等信息
该表中存放的数据是遍历匹配的如:

id   student_id     lecture_id     grade    note
---  ----------     ----------     -----    -----
001  2014420301     01             80
002  2014420301     02             70
003  2014420301     03             90
004  2014420302     01             60
005  2014420302     02             76
006  2014420302     03             65
007  2014420303     01             85
008  2014420303     02             90
009  2014420303     03             75

再来分析一课程表
课程表中的每一条记录代表一门课程,因为包含了一门课程的基本信息
课程名称
最起码的结构和数据应该是:
id   lecture_name    note
---  ------------    ----
01   语文            
02   数学
03   英语
04   体育 

比较而言,两种表的数据存在很大的差异,这种差异是什么啊?
主要表现在字段的重复性上
id字段的数据都是不重复的
lecture_name的数据也是不重复的
stdent_id和lecture_id是重复的,但这种重复不是随机出现的
而且两种重复又是有差异的
student_id的数据是连续重复,间隔不重复
lecture_id的数据是连续不重复,间隔重复
这是因为
student_id表示学生
lecture_id表示课程
现实中,
一名学生对应多个课程,是一个一对多的关系
这样一来,
在表中表现为:同一个student_id的多个数据对应多个不同的lecture_id
且student_id数据的个数等于lecture_id的数据的个数
而另外一名学生也对应多个相同的课程,这样又多了一个一对多的关系
于是又在表中表现为:同一个student_id对应多个不同的lecture_id
将这些一对多的数据拼接起来
就形成了那种重复的特点:连续重复,间隔不重复,连续不重复,间隔重复
这里的逻辑是:
例如
一个学生对应语数外三个课程
那如果有多个学生会怎样呢?
多个一对多的拼接啊
这里要清楚一个一对多是什么样!
就知道多个一对多拼接后是什么样了!!
这告诉我们表中的字段也是存在对应关系的
grade的数据也会是重复的,但是这种重复是随机出现的
那么这里再思考一个问题:
为什么课程表的数据不重复
因为两个主要字段的数据是一对一的
注意这里的重复取决于主要的价值的字段的对应关系
在学生课程表中
id只是每条记录的编号,没有实际意义的,不用考虑该id

在任何一张表,这样的id都是不会重复的,

id作为编号是有实际意义上的区分的

注:一言接着一语的是自然谈话,过渡很自然,谁都能想到,也就没什么趣味,
   把中间的过程省略,表现的像想到别人前面去了,就会让人惊讶
   反应好快,说的好对好有趣,这就是娱乐了
   并不是你想不到,而是想到你前面去了
   当想到你前面去之后,你也就只能叹气自己怎么没想到呢? 

毛囊炎会时不时的冒出要犯病的信号,
当这种信号出现的时候
不要太劳累,把觉睡好,免疫力上来之后自然就好了            

现在假设已经写好了dao接口并定义了方法
当然也写好了bean
假设这个方法叫做getStudentLectureByStuId
这个方法能够执行mapper中的sql

先写一个StudentLectureBean类
//类后面不跟小括号
public class StudentLectureBean{
    public int id;
    public String studentId;//不能定义成student_id
    public String lectureId;//
    public String grade;
    public String note;

}


dao接口中的方法
    public interface StudentLectureDao{
        public List<StudentLectureBean> getStudentLectureByStuId(String stuId);
        //接口中的方法不用花括号,用分号代替
        //按Student_id查询,肯定会获得三条记录
        //每一条记录对应一个Bean
        //因此返回结果肯定是一个bean的集合
    }


写dao对应的mapper
<?xml version="" encoding=""?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper//EN"
 "http://mybatis.org.....">

<mapper namespace="com.learn.chapter4.dao.StudentLectureDao">
 
    <select id="getStudentLectureByStuId" resultType="com.learn.chapter4.entity.StudentLectureBean">
         SELECT id,student_id AS studentId,lecture_id AS lectureId,grade
         FROM t_student_lecture
         WHERE student_id = #{studentId}
         //studentId表示从实体中获取的数据作为参数
         //当然这里也假设获取的数据赖在实体
         //但获取的数据不止来自实体
         //还可以来自其他mapper中的查询结果!!
    </select>

</mapper>


如果进行了这样的查询的话
必然获取三条记录,分别映射到bean中,发现问题了,映射不上
所以得取别名解决
映射上了,
那么,三个bean的实例组成了一个集合,
每个集合中包含的属性分别是id,studentId,lectureId,grade
问题就出现在这里,
没人知道lecture_id到底表示什么?
如果知识单纯的想在前端展示此数据
且课程数目不是很多的话
可以通过数据字典函数的方式进行
还可以通过级联的方式来解决:

  1 改写mapper,用resultMap的方式自己定义映射方式如下:
    
<?xml version="" encoding=""?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper//EN"
 "http://mybatis.org.....">

<mapper namespace="com.learn.chapter4.dao.StudentLectureDao">
    //如果使用了resultMap的方式,那么就不用采用自动映射的机制了
    //首先取消自动映射的机制
    //先给映射规则定义名字
    //指定映射将查询结果给哪个bean
    <resultMap id="StudentLectureMap" type="com.learn.chapter4.entity.StudentLectureBean">
         <id property="id" column="id"/>
         <result property="studentId" column="studentId"/>
         //这里进行改动了
         //想法是: 已经根据student_id查到lecture_id
         //接下来只要拿着lecture_id
         //到课程表中进行查询,将查询到的结果放到这里定义一个属性当中
         //由于一个lecture只能查到唯一一条记录
         //要做这件事情<result>标签是做不到的
         //这里只能用<association>标签
         //<associtation>好似一个程序一样所以要配置一下输入和输出
         //输出存放在lecture属性中,用property指定
         //输入lecture_id用column指定
         //执行的查询sql用select来指定
         <associtation property="lecture" column="lecture_id"
                       select="com.learn.chapter4.dao.getLectureById"/>
         //到这里,就要做两件事情:
         //在bean中添加lecture属性
         //写LectureBean dao 和 mapper

         <result property="grade" column="grade"/>
         <result property="note" column="note" />
    </resultMap>    

    <select id="getStudentLectureByStuId" resultType="com.learn.chapter4.entity.StudentLectureBean">
         SELECT id,student_id,lecture_id,grade
         FROM t_student_lecture
         WHERE student_id = #{stuId}
         //stuId表示从dao中获取的数据作为参数
         //但获取的数据不止可以来自dao类
         //还可以来自实体类!!
    </select>

</mapper>
最后,只关注这个StudentLecture的这个mapper:
不禁会发现一个问题:
如果按照stuId来查询数据,那么获得的数据记录就不可能只有一条啊
因为一个学生不可能只学一门课程
当这条sql执行完之后
我们只能用所有查到的lecture_id的数据挨个去进行sql查询啊
因为lecture_id不可能只有一个数据啊
最后还要把查询到的数据放到一个集合Bean类中
这要怎么实现呢?
或者说这个问题该怎么解决的呢?
等我找到答案在把这个补上吧
因为这里为了方便数据只有一条可以这么做
:也就是假设一个学生只修一门课程!!


写LectureBean 
public class LectureBean{
    public String id;
    public String lecture_name;
    public String note;

}

写dao接口

public interface LectureDao{
    public LectureBean getLectureByLectureId(String lectId);

}


写 mapper

<?xml version="" encoding=""?>
<!DOCTYPE mapper
 PUBLIC ""
 "">
//思考的步骤和编写的步骤肯定是冲突的
//这会让人觉得很不自然
<mapper namespace="com.learn.chapter4.dao.LectureDao">
   <select id="getLectureByLectureId" resultType="com.learn.chapter4.entity.LectureBean">
       SELECT id,lecture_name AS lectureName,note
       FROM t_lecture
       WHERE id=#{lectId}
   </select>
</mapper>

最后,只关注这个StudentLecture的这个mapper:
不禁会发现一个问题:
如果按照stuId来查询数据,那么获得的数据记录就不可能只有一条啊
因为一个学生不可能只学一门课程
当这条sql执行完之后
我们只能用所有查到的lecture_id的数据挨个去进行sql查询啊
因为lecture_id不可能只有一个数据啊
最后还要把查询到的数据放到一个集合Bean类中
这要怎么实现呢?
或者说这个问题该怎么解决的呢?
等我找到答案在把这个补上吧
因为这里为了方便数据只有一条可以这么做
:也就是假设一个学生只修一门课程!!

猜你喜欢

转载自blog.csdn.net/weixin_42204641/article/details/81536844