联合查询
<!-- 处理关系查询相关的复杂返回数据类型(本例中未曾用到) -->
<resultMap type="SchoolStudent" id="SchoolStudentMap">
<id property="schoolStudentId" column="schoolStudentId"/>
<result property="teacher" column="teacher"/>
<result property="teacherAge" column="teacherAge"/>
<association property="studentId" column="studentId" javaType="int">
<id property="studentId" column="studentId"/>
<result property="name" column="name"/>
<result property="age" column="age"/>
</association>
</resultMap>
<select id="selectSchoolStudentJoin" resultMap="SchoolStudentMap">
select * from schoolStudent join student on schoolStudent.studentId = student.studentId
</select>
id="SchoolStudentMap":调用该resultMap的id
type="SchoolStudent":返回的类型
id property="schoolStudentId":SchoolStudent类中的id主键字段
column="schoolStudentId":schoolstudent表中与schoolStudentId相对应的字段
result property="teacher" column="teacher":SchoolStudent类中其它字段
association property="studentId":与SchoolStudent关联的子查询表的配置,这里的property属性是SchoolStudent类中与子查询类中关联的属性
column="studentId":与SchoolStudent关联的子查询表的配置,这里的column属性是SchoolStudent表中对应property的字段
javaType="int":返回到SchoolStudent类中时的值的类型
association中的其它配置与SchoolStudent主表配置相同,不过是关联表中的属性与对应的字段
构造函数查询
<resultMap id="SchoolStudentConstructor" type="SchoolStudent" > <id property="id" column="schoolStudent.id" /> <result property="teacher" column="teacher" /> <result property="age" column="age" /> <association property="student" column="studentId" javaType="Student"> <constructor> <idArg column="studentId" javaType="int"/> <arg column="name" javaType="String"/> <arg column="zhuangtai" javaType="int"/> </constructor> </association> </resultMap>
association property="student":与SchoolStudent关联的子查询表的配置,这里的property属性是SchoolStudent类中的属性(关联表的类对象)
column="studentId":与SchoolStudent关联的子查询表的配置,这里的column属性是SchoolStudent表中对应property的字段,该字段与关联表的某字段关联
javaType="Student":返回到SchoolStudent类中时的值的类型,这里只能是关联表的类对象(别名)
constructor 设置关联表的类中的构造函数的参数。这里传入了多少参数,类中的构造函数中就有多少参数。这里的int对应类中构造函数中数据类型为Integer。值得注意的是,使用这种方式,在类中必须包含一个无参的构造函数;查询的主表与关联表中的字段名不能相同(除关联字段以外)
子查询
联合查询一次查询,占用资源大;子查询N+1次查询,占用资源可大可小。MyBatis通过懒加载的方式处理了子查询N+1次查询的问题。懒加载的原理就是先查询需要返回的主表的类对象,当用到所包含的子类对象时,才会去查询所包含的子类对象
使用懒加载必须要先启动懒加载(将以下代码加入MyBatisConfig.xml文件中:需要放在创建别名之前)
<!-- 启动懒加载 --> <settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="aggressiveLazyLoading" value="false"/> </settings>
在对应的map.xml中写查询
<resultMap id="SchoolStudentSubMap" type="SchoolStudent" > <id property="id" column="schoolStudent.id" /> <result property="teacher" column="teacher" /> <result property="age" column="age" /> <association property="student" column="studentId" javaType="Student" select="getStudentById"> </association> </resultMap> <select id="selectSchoolStudentJoin" resultMap="SchoolStudentSubMap"> select * from schoolStudent where schoolStudent.studentId in (select studentid from student) </select>
以上代码中association的select属性是用于调用查询并返回student子表类对象的select
<select id="getStudentById" parameterType="int" resultType="Student"> select * from student where studentId=#{studentId} </select>
测试与结果
List<SchoolStudent> schoolStudents = sqlSession.selectList("selectSchoolStudentJoin"); //for(SchoolStudent schoolStudent : schoolStudents) { // System.out.println(schoolStudent.getTeacher()); // System.out.println("========================"); // int id = schoolStudent.getStudent().getStudentId(); // System.out.println("学生id" + id); //} if (schoolStudents != null) { System.out.println(schoolStudents.get(0).getTeacher()); System.out.println("========================"); int id = schoolStudents.get(0).getStudent().getStudentId(); System.out.println("学生id" + id); }
控制台输出
只使用了其中一条数据
2017-12-15 22:58:31,801 [main] DEBUG [/.selectSchoolStudentJoin] - ==> Preparing: select * from schoolStudent where schoolStudent.studentId in (select studentid from student)
2017-12-15 22:58:31,864 [main] DEBUG [/.selectSchoolStudentJoin] - ==> Parameters:
2017-12-15 22:58:31,947 [main] DEBUG [/.selectSchoolStudentJoin] - <== Total: 2
李四的教师
========================
2017-12-15 22:58:31,949 [main] DEBUG [/.getStudentById] - ==> Preparing: select * from student where studentId=?
2017-12-15 22:58:31,950 [main] DEBUG [/.getStudentById] - ==> Parameters: 2(Integer)
2017-12-15 22:58:31,953 [main] DEBUG [/.getStudentById] - <== Total: 1
学生id2
使用了全部数据(测试中使用for)
2017-12-15 23:09:27,260 [main] DEBUG [/.selectSchoolStudentJoin] - ==> Preparing: select * from schoolStudent where schoolStudent.studentId in (select studentid from student) 2017-12-15 23:09:27,305 [main] DEBUG [/.selectSchoolStudentJoin] - ==> Parameters: 2017-12-15 23:09:27,377 [main] DEBUG [/.selectSchoolStudentJoin] - <== Total: 2 李四的教师 ======================== 2017-12-15 23:09:27,378 [main] DEBUG [/.getStudentById] - ==> Preparing: select * from student where studentId=? 2017-12-15 23:09:27,378 [main] DEBUG [/.getStudentById] - ==> Parameters: 2(Integer) 2017-12-15 23:09:27,380 [main] DEBUG [/.getStudentById] - <== Total: 1 学生id2 王五的教师 ======================== 2017-12-15 23:09:27,381 [main] DEBUG [/.getStudentById] - ==> Preparing: select * from student where studentId=? 2017-12-15 23:09:27,381 [main] DEBUG [/.getStudentById] - ==> Parameters: 3(Integer) 2017-12-15 23:09:27,383 [main] DEBUG [/.getStudentById] - <== Total: 1 学生id3
特别注意:
- 这里的联合查询,在SchoolStudent表中都包含了关联的子表对象。相关联的表中的字段名除关联字段以外不能有相同的,否则便得不到对应的值。比如SchoolStudent中有id,而Student表中同样有id,那么查询时,得不到id的值