背景
要解决的问题:
实体类中老师是学生的属性,是一个对象,但是数据库中对应的学生表格中老师的属性为tid是一个int型,
将数据库中老师信息于学生表格中老师的信息对应起来.(多个学生一个老师)
按照查询嵌套处理
先查询所有学生,然后根据学生的tid查询对应的老师, 子查询。
接口中的方法不用改变,要改变的是 StudentMapper.xml 中怎么用 SQL
<!-- 思路:
1.查询所有的学生信息
2.根据查询出来的学生的tid,寻找对应的老师!
子查询 -->
<select id="getStudent" resultMap="StudentTeacher">
select * from student
</select>
<resultMap id="StudentTeacher" type="Student">
<!--属性和字段本身就能对应起来的,可以不写-->
<result property="id" column="id"/>
<result property="name" column="name"/>
<!--复杂的属性,我们需要单独处理
对象: association 集合: collection-->
<!-- property 对象属性 colum 数据库列名-->
<association property="teacher" column="tid" javaType="Teacher" select="getTeacher"/>
</resultMap>
<!--根据 id 查询老师 只有一个参数可以不写-->
<select id="getTeacher" resultType="Teacher">
select * from teacher where id = #{id}
</select>
association 可以指定关联的 JavaBean 对象, property 代表关联对象的属性,column 为对应的数据库中相应表的字段.
本题中数据库字段 tid 与 teacher 也不一致,所以要指定一个查询,通过 tid 查询到 teacher 对象。
这种方法本质上其实是嵌套了一个子查询,即先查学生再查对应的老师,对 Student 执行一次查询,在 Student 里再对 Teacher 执行一次查询。
按照结果嵌套处理
先用 SQL 语句将需要的属性、对象统一查询出来,再通过 resultMap 中 association 使查询出来的字段与属性对应.
在接口中再创建一个方法
public interface StudentMapper {
...
// 获取所有学生及其对应的老师信息,按照结果嵌套处理
public List<Student> getStudent2();
}
再写这个方法使用的 SQL 语句和结果集映射
<!--按照结果嵌套处理-->
<select id="getStudent2" resultMap="StudentTeacher2">
select s.id sid,s.name sname,t.name tname
from student s,teacher t
where s.tid = t.id;</select>
<resultMap id="StudentTeacher2" type="Student">
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<association property="teacher" javaType="Teacher">
<result property="name" column="tname"/>
</association>
</resultMap>
测试方法中直接把 mapper 调用的方法改成 getStudent2 就行了,直接看结果
运行效果如下:
老师的 id 都是0,原因很显然,这种方法是先查属性再做对应,这里一没查老师的 id 二没做对应,所以老师的 id 肯定显示不出来。
将老师的id也加进来
<!--按照结果嵌套处理-->
<!--查询的结果 本质上还是个 Student-->
<resultMap id="StudentTeacher2" type="Student">
<!--属性和字段本身就能对应起来的,可以不写-->
<result property="id" column="sid"/>
<result property="name" column="sname"/>
<!--对应,要查找的属性叫 teacher 它是 Teacher 类型的-->
<association property="teacher" javaType="Teacher">
<!--将查找出来的 tname 与 老师中的属性 name 对应-->
<!-- ++++++加入 老师id 的对应-->
<result property="id" column="tid"/>
<result property="name" column="tname"/>
</association>
</resultMap>
<select id="getStudent2" resultMap="StudentTeacher2">
<!-- ++++++多查一个 t.id 出来-->
select s.id as sid, s.name as sname, t.id as tid, t.name as tname
from student s, teacher t
where s.tid = t.id
</select>
总结
总的来说,多对一的查询,有两种方法
按照查询嵌套处理:本质上是子查询,用当前查出来的信息再做一次查询
按照结果嵌套处理:本质上是联表查询,直接查出来所有信息再给它们对应上
我感觉第二种更好用,即没改变 SQL 本身,也不用写多个查询标签。
注意:如果在 IDEA 中设置了 SQL Dialects,则 SQL 语句中的表名前要加上数据库库名,否则会报红,不过其实不影响执行(猜测是 IDEA 无法识别到这张表,但执行的时候数据源中指定了数据库,所以能查到正确的表)。但去掉设置后 IDEA 无法给出输入提示了,如表名要纯手打。为了干净一点我后面还是去掉了。
提醒:在 IDEA 中使用数据库 Console,一定要对着要使用的数据库打开 Console,否则会识别不了表(在表前加上数据库名也行,不过多丑啊)。