Mybatis-查询处理一对一和一对多
前期準備
數據庫資源準備:
CREATE DATABASE mybatis;USE mybatis;CREATE TABLE `teacher`(`id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '主鍵id',`name` VARCHAR (30) NOT NULL COMMENT '姓名' )ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO teacher(`name`) VALUES ('胡老師'); INSERT INTO teacher(`name`) VALUES ('黃老師');CREATE TABLE `student`(`id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '主鍵id',`name` VARCHAR (30) NOT NULL COMMENT '姓名',`tid` INT DEFAULT NULL,KEY `fktid`(`tid`),CONSTRAINT `fktid` FOREIGN KEY (`tid`) REFERENCES `teacher`(`id`) )ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO `student`( `name`,`tid`) VALUES ('小明',1); INSERT INTO `student`( `name`,`tid`) VALUES ('小紅',1); INSERT INTO `student`( `name`,`tid`) VALUES ('小剛',1); INSERT INTO `student`( `name`,`tid`) VALUES ('小張',2); INSERT INTO `student`( `name`,`tid`) VALUES ('小麗',2); INSERT INTO `student`( `name`,`tid`) VALUES ('小美',2);雖然只有簡單的兩個表,但是可以很明顯的反映一對一和一對多的情景。
如果學生對老師,就是一對一的情況,如果是老師對學生,就是一對多。
我們可以理解為一個學生有一個老師,但是一個老師就包含多個學生。
這里不再贅述Mybatis的配置,僅列出較為重要的代碼。
一對一
這里我們就以一個學生包含一個唯一的老師為例:
需求:這里我們需要查詢出學生的信息,其學生的信息包含老師的信息。
實體類如下(為節省文章篇幅,省略了實體類的構造方法、getter、setter和toString):
Teacher類
Student類
//學生 public class Student {private int id;private String name;//學生要關聯一個老師 一個學生對應一個老師private Teacher teacher; }TeacherMapper接口(由于這里演示僅需要這一個方法,為了簡便就直接使用注解了):
package com.ara.dao;import com.ara.pojo.Teacher; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select;public interface TeacherMapper {/*** 通過老師的id查詢出老師的信息** @param id 老師的唯一主鍵id* @return 返回id對應的老師信息*/@Select("select * from teacher where id = #{id}")Teacher getTeacherById(@Param("id") int id);}StudentMapper接口:
package com.ara.dao;import com.ara.pojo.Student; import org.apache.ibatis.annotations.Param;public interface StudentMapper {/*** 根據學生的主鍵id查詢學生的詳細信息 其中包含老師的信息* 方式一** @param id 主鍵id* @return 返回對應的學生信息*/Student getStudentById1(@Param("id") int id);/*** 根據學生的主鍵id查詢學生的詳細信息 其中包含老師的信息* 方式二** @param id 主鍵id* @return 返回對應的學生信息*/Student getStudentById2(@Param("id") int id);}StudentMapper.xml文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ara.dao.StudentMapper"><!-- 直接使用聯表查詢 start --><select id="getStudentById1" parameterType="_int" resultMap="StudentMap1">select s.id sid,s.name sname,t.id tid,t.name tname from student s,teacher t where s.tid = t.id and s.id = #{id};</select><resultMap id="StudentMap1" type="Student"><result column="sid" property="id" /><result column="sname" property="name" /><!--由于這里屬于嵌套組合的屬性 我們采用association標簽因為我們需要對Student中Teacher進行再次封裝 所以我們需要制定如下屬性property:Student類中的屬性名javaType:制定屬性的Java類型--><association property="teacher" javaType="Teacher"><result column="tid" property="id" /><result column="tname" property="name" /></association></resultMap><!-- 方式一:直接使用聯表查詢 end --><!-- 方式二:查詢中嵌套查詢 start --><select id="getStudentById2" parameterType="_int" resultMap="StudentMap2">select * from student where id = #{id};</select><resultMap id="StudentMap2" type="Student"><result column="id" property="id" /><result column="name" property="name" /><!--由于這里屬于分兩次查詢 所以我們直接利用外鍵這列來查詢Teacher信息column:查詢后的列名property:Student類中的屬性名javaType:制定屬性的Java類型select:需要引用的查詢Id--><association column="tid" property="teacher" javaType="Teacher" select="com.ara.dao.TeacherMapper.getTeacherById"/></resultMap><!-- 方式二:查詢中嵌套查詢 end --></mapper>測試代碼:
package com.ara.test;import com.ara.dao.StudentMapper; import com.ara.pojo.Student; import com.ara.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;public class StudentMapperTest {@Testpublic void getStudentByIdTest1(){SqlSession sqlSession = MybatisUtils.getSqlSession();StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);Student student = studentMapper.getStudentById1(1);System.out.println(student);sqlSession.close();}@Testpublic void getStudentByIdTest2(){SqlSession sqlSession = MybatisUtils.getSqlSession();StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);Student student = studentMapper.getStudentById2(5);System.out.println(student);sqlSession.close();}}getStudentByIdTest1結果:
getStudentByIdTest2結果:
兩種方式都可以查詢出結果,但是兩者的過程并不相同,聯表查詢雖然SQL語句較為復雜,但是它的執行就只運行了一條SQL語句,嵌套查詢雖然SQL語句簡單,但是它卻執行了兩個SQL語句,具體開發中,還是要根據自己的需要來酌情選擇。
一對多
這里我們就以一個老師有多個學生為例:
需求:根據對應老師的Id查詢老師的信息及其所有的學生信息。
實體類如下(為節省文章篇幅,省略了實體類的構造方法、getter、setter和toString):
Student類:
package com.ara.pojo;//學生類 public class Student {private int id;private String name;//學生要關聯一個老師idprivate int tid;}Teacher類:
package com.ara.pojo;import java.util.List;//老師 public class Teacher {private int id;private String name;//老師含有多個學生private List<Student> students;}StudentMapper接口:
package com.ara.dao;import com.ara.pojo.Student; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select;import java.util.List;public interface StudentMapper {/*** 老師的id查詢其學生列表* @param tid 老師id* @return 返回學生列表*/@Select("select * from student where tid = #{tid}")List<Student> getStudentByTId(@Param("tid")int tid);}TeacherMapper接口:
package com.ara.dao;import com.ara.pojo.Teacher; import org.apache.ibatis.annotations.Param;public interface TeacherMapper {/*** 根據教師的id查詢教師的信息 包含其名下學生信息* 方式一** @param id 教師id* @return 返回對應教師的信息*/Teacher getTeacherById1(@Param("id") int id);/*** 根據教師的id查詢教師的信息 包含其名下學生信息* 方式二** @param id 教師id* @return 返回對應教師的信息*/Teacher getTeacherById2(@Param("id") int id);}TeacherMapper.xml文件:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ara.dao.TeacherMapper"><!-- 方式一:結果嵌套查詢 start --><select id="getTeacherById1" parameterType="_int" resultMap="teacherInfoMap1">select t.id tid,t.name tname,s.id sid,s.name sname from teacher t,Student s where t.id = s.tid and t.id = #{id}</select><resultMap id="teacherInfoMap1" type="Teacher"><result column="tid" property="id" /><result column="tname" property="name" /><!--復雜的屬性 我們需要單獨處理 集合使用collectionjavaType:指定屬性的類型ofType:指定集合中的泛型信息--><collection property="students" ofType="Student" ><result column="sid" property="id" /><result column="sname" property="name" /><result column="tid" property="tid" /></collection></resultMap><!-- 方式一:結果嵌套查詢 end --><!-- 方式二:查詢嵌套查詢 start --><select id="getTeacherById2" parameterType="_int" resultMap="teacherInfoMap2" >select * from teacher where id = #{id};</select><resultMap id="teacherInfoMap2" type="Teacher"><result column="id" property="id" /><result column="name" property="name" /><!--復雜的屬性 我們需要單獨處理 集合使用collectioncolumn:指定需要再次查詢的列名property:指定Teacher中的students屬性javaType:指定Teacher中的students屬性的Java類型ofType:指定Teacher中的students屬性的Java類型的泛型類型select:指定我們需要做再次查詢的方法id--><collection column="id" property="students" javaType="ArrayList" ofType="Student" select="com.ara.dao.StudentMapper.getStudentByTId"/></resultMap><!-- 方式二:查詢嵌套查詢 end --></mapper>測試代碼如下:
package com.ara.dao.test;import com.ara.dao.TeacherMapper; import com.ara.pojo.Teacher; import com.ara.utils.MybatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Test;public class TeacherMapperTest {@Testpublic void getTeacherByIdTest1(){SqlSession sqlSession = MybatisUtils.getSqlSession();Teacher teacher = sqlSession.getMapper(TeacherMapper.class).getTeacherById1(1);System.out.println(teacher);sqlSession.close();}@Testpublic void getTeacherByIdTest2(){SqlSession sqlSession = MybatisUtils.getSqlSession();Teacher teacher = sqlSession.getMapper(TeacherMapper.class).getTeacherById2(2);System.out.println(teacher);sqlSession.close();}}getTeacherByIdTest1測試結果:
getTeacherByIdTest2測試結果:
這兩種方式都能實現我們的需求,但是也存在著上述一對一的情況,就是聯表查詢的SQL語句雖然較為復雜,但是它只運行了一條SQL,通過查詢中嵌套查詢,雖然SQL簡單了,但是它分了兩條SQL進行查詢。
都各有優缺點,結果中嵌套只是理解起來可能較為復雜,但是它的效率就相對較高,查詢中嵌套查詢,雖然SQL語句很簡單,但是它的執行效率就相對來說較為低下。
實際的開發中,根據具體的情況具體斟酌即可。
總結
以上是生活随笔為你收集整理的Mybatis-查询处理一对一和一对多的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 法国童话故事《小王子》读后感
- 下一篇: Keystone认证服务详细操作流程