mybatis的查詢效率問題

mybatis的查詢效率問題

1.配置信息

如今有學生和老師兩張表老師的Mapperweb

1.老師Mapper


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.abc.mapper.TeacherMapper">
    <resultMap type="com.abc.domian.Teacher" id="supervisorResultMap">
        <id property="id" column="oid"/>
        <result property="name" column="name"/>
        <result property="gender" column="gender"/>
        <result property="researchArea" column="research_area"/>
        <result property="title" column="title"/>
        <!-- <collection property="supStudent" resultMap="com.abc.mapper.StudentMapper.StudentResultMap"></collection> -->
        <collection property="supStudent" column="id" select="com.abc.mapper.StudentMapper.getStudentByTeacherId" resultMap="com.abc.mapper.StudentMapper.StudentResultMap"></collection>
    </resultMap>
    <select id="getById" parameterType="int" resultMap="supervisorResultMap">
        select t.id as oid ,t.name,t.gender,t.research_area,t.title,s.id,s.name as s_name,s.gender,s.major,s.grade,s.supervisor_id from student s , teacher t where s.supervisor_id = t.id
        and t.id=#{id}
    </select>
    <select id="getAllTeacher" parameterType="map" resultMap="supervisorResultMap">
        select * from teacher
    </select>
</mapper>

2. 學生mapper


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.abc.mapper.StudentMapper">
    <resultMap type="com.abc.domian.Student" id="StudentResultMap">
        <id property="id" column="id"/>
        <result property="name" column="s_name"/>
        <result property="gender" column="gender"/>
        <result property="major" column="major"/>
        <result property="grade" column="grade"/>
        <association property="supervisor" resultMap="com.abc.mapper.TeacherMapper.supervisorResultMap">
        </association>
    </resultMap>
    <select id="getById" parameterType="int" resultMap="StudentResultMap">
        select * from student where id = #{id}
    </select>
    <!-- #name 中那麼大小寫敏感 useGeneratedKeys設置爲true是由數據庫自動生成逐漸 keyProperty 指定把得到到的主鍵值注入 到Student的id屬性-->
    <insert id="add" parameterType="com.abc.domian.Student" useGeneratedKeys="true" keyProperty="id">
        insert into student(name,gender,major,grade) values(#{name},#{gender},#{major},#{grade})
    </insert>
    <update id="update" parameterType="com.abc.domian.Student" >
        update student set gender = #{gender} where id= #{id}
    </update>
    <!-- org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.abc.mapper.StudentMapper.delete 若是id和Mapper不匹配的話會拋出上述的錯誤 -->
    <delete id="delete" parameterType="com.abc.domian.Student">
        delete from student where id = #{id}
    </delete>
    
    <select id="getStudnetAndTeacher" parameterType="int" resultMap="StudentResultMap">
        select * from student s ,teacher t where s.supervisor_id = t.id and s.id = #{id}
    </select>   
    <insert id="addStudent" parameterType="com.abc.domian.Student" useGeneratedKeys="true" keyProperty="id">
        insert into student(name,gender,major,grade,supervisor_id)
        values(#{name},#{gender},#{major},#{grade},#{supervisor.id})
    </insert>
    <select id="getStudentByTeacherId" parameterType="string" resultMap="StudentResultMap">
        select * from student where supervisor_id = #{id}
    </select>
</mapper>

2. 問題

2.一、關聯查詢時效率的問題---經過老師查找學生getById的形式

配置文件:sql

2.1.1老師:
<resultMap type="com.abc.domian.Teacher" id="supervisorResultMap">
        <id property="id" column="oid"/>
        ...
        <collection property="supStudent" column="id" select="com.abc.mapper.StudentMapper.getStudentByTeacherId" resultMap="com.abc.mapper.StudentMapper.StudentResultMap"></collection>
    </resultMap>
    <select id="getById" parameterType="int" resultMap="supervisorResultMap">
        select t.id as oid ,t.name,t.gender,t.research_area,t.title,s.id,s.name as s_name,s.gender,s.major,s.grade,s.supervisor_id from student s , teacher t where s.supervisor_id = t.id
        and t.id=#{id}
    </select>
2.1.2 學生
<resultMap type="com.abc.domian.Student" id="StudentResultMap">
        <id property="id" column="id"/>
        ...
        <association property="supervisor" resultMap="com.abc.mapper.TeacherMapper.supervisorResultMap">
        </association>
    </resultMap>

經過上面的配置咱們能夠看出來;老師查詢學生的時候,使用經過select的配置進行查詢的,若是咱們經過這種方式來查詢學生是會致使sql語句的增多;咱們查看控制檯後,發現輸出的內容爲:數據庫

select t.id as oid ,t.name,t.gender,t.research_area,t.title,s.id,s.name as s_name,s.gender,s.major,s.grade,s.supervisor_id from student s , teacher t where s.supervisor_id = t.id and t.id=? select * from student where supervisor_id = ? select * from student where supervisor_id = ? select * from student where supervisor_id = ? select * from student where supervisor_id = ? 

sql語句的個數明顯不少,所以不建議經過該方式進行查詢;
解決辦法:
若是咱們將老師的mapper映射文件:apache

<collection property="supStudent" column="id" select="com.abc.mapper.StudentMapper.getStudentByTeacherId" resultMap="com.abc.mapper.StudentMapper.StudentResultMap"></collection>

修改成:mybatis

<collection property="supStudent" resultMap="com.abc.mapper.StudentMapper.StudentResultMap"></collection>

在進行查詢的時候咱們發現會只輸出一句話;app

select t.id as oid ,t.name,t.gender,t.research_area,t.title,s.id,s.name as s_name,s.gender,s.major,s.grade,s.supervisor_id from student s , teacher t where s.supervisor_id = t.id and t.id=? 

在進行關聯映射的時候儘可能不要使用collection中的select語句,這樣會致使查詢語句增多的問題;能夠本身書寫sql語句,讓mybatis進行映射dom

2.2 關聯查詢別稱起到的做用

根據輸出的內容我麼還能夠發現另一些問題:
一、經過自定義的sql語句進行查詢時管理的查詢出的對象沒有null
二、經過select的配置查詢的記錄是由null只出現的;
關聯查詢別稱起到的做用ide

當咱們吧select * from teacher這條語句進行替換成自定義的sql時;ui

<select id="getAllTeacher" parameterType="map" resultMap="supervisorResultMap"> select t.id as oid ,t.name,t.gender,t.research_area,t.title,s.id,s.name as s_name,s.gender,s.major,s.grade,s.supervisor_id from student s , teacher t where s.supervisor_id = t.id </select> 

enter description here

使用Mybatis時,儘可能使用一條sql語句去完成查詢spa

2.3 關聯是對參數的賦值問題


驗證關聯查詢的時候使用的時sql名稱仍是屬性名稱,sql語句查詢時參數的賦值依據
enter description here
enter description here

參數的賦值結果是由parameterType="map"類型決定的若是爲對象,那麼從屬性中得到,若是爲map,參數有map中的鍵決定

2.4 關聯是對參數的賦值問題

若是我想經過老師的專業,來查詢學士,注意下面兩天sql語句的不一樣:

SELECT s.id, t.id , s.name , t.gender, t.research_area, t.title, t.name, s.gender, s.major, s.grade, s.supervisor_id FROM student s, teacher t WHERE s.supervisor_id = t.id and t.research_area = '1' 

enter description here

SELECT t.id , s.name , t.gender, t.research_area, t.title, s.id, t.name, s.gender, s.major, s.grade, s.supervisor_id FROM student s, teacher t WHERE s.supervisor_id = t.id and t.research_area = '1' 

enter description here
數據庫中的sql條數爲
enter description here

使用一條sql語句時,注意要返回的結果是誰,若是返回多的一方,請將多的一方id放置到第一列,若是返回的是少的一方,請將少的一方id放置到第一列,
即:根據 resultMap="StudentResultMap" 對象的id放置第一列

enter description here

2.5 賦值的參數類型有誰決定

enter description here

由parameterType="map"去決定值

2.6若是使用了關聯查詢,而且配置了column,查詢時參數的設置

enter description here

使用column活着,column對應的屬性或者該屬性對應的列 均可以查詢出結果集sql

2.7 實體類有相同的字段,查詢數據會被覆蓋

在查詢時,有學生和老師兩個對象,可是學生中的name和老師的那麼屬性是一致的,使用關聯對象進行查詢的時候,就會遇到學生的name值被覆蓋給了老師如圖:
enter description here
查詢到的老師的姓名都是學生的,這個時候有兩種解決辦法:
a、 經過修改數據庫,將學生和老師的兩個字段都進行修改;讓他們的字段不同,這樣映射也就不會有錯誤;
b、另一種方式是不修改數據庫的字段,修改映射文件中的result

<id column="tea_id" property="id" jdbcType="INTEGER" />
   <result column="tea_name" property="name" jdbcType="VARCHAR" />
   <result column="tea_gender" property="gender" jdbcType="VARCHAR" />
   <result column="tea_research_area" property="researchArea" jdbcType="VARCHAR" />
   <result column="tea_title" property="title" jdbcType="VARCHAR" />

以及

<sql id="Base_Column_List" >
   id as tea_id, name as tea_name, gender as tea_gender, research_area as tea_research_area, title as tea_title
 </sql>

來完成修改,固然查詢的sql語句也是須要修改的

<select id="queryStudentAndTeacher" resultMap="BaseResultMap" useCache="true" >
   SELECT
       s.id,
       s.`name`,
       s.gender,
       s.major,
       s.grade,
       s.supervisor_id ,
       t.id as tea_id,
       t.`name` as tea_name,
       t.gender as tea_gender,
       t.research_area  as tea_research_area,
       t.title  as tea_title
   FROM
       student s
   LEFT JOIN teacher t ON s.supervisor_id = t.id
 </select>

3 資料

/* Navicat MySQL Data Transfer Source Server : localhost_3306 Source Server Version : 50528 Source Host : localhost:3306 Source Database : courseman Target Server Type : MYSQL Target Server Version : 50528 File Encoding : 65001 Date: 2015-04-21 16:54:27 */
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `gender` varchar(255) DEFAULT NULL, `major` varchar(255) DEFAULT NULL, `grade` varchar(255) DEFAULT NULL, `supervisor_id` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES ('1', '李林', '男', '計算機科學與技術', '2011', '1');
INSERT INTO `student` VALUES ('2', '陳明', '男', '軟件技術', '2012', '1');
INSERT INTO `student` VALUES ('3', '李林1', '男', '計算機科學與技術', '2011', '2');
INSERT INTO `student` VALUES ('4', '陳明2', '男', '軟件技術', '2012', '2');
-- ----------------------------
-- Table structure for teacher
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `gender` varchar(255) DEFAULT NULL, `research_area` varchar(255) DEFAULT NULL, `title` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of teacher
-- ----------------------------
INSERT INTO `teacher` VALUES ('1', '陳老師', '男', '計算機', '暫無');
INSERT INTO `teacher` VALUES ('2', '郝老師', '男', '無語', '五');
相關文章
相關標籤/搜索