zoukankan      html  css  js  c++  java
  • mybatis的查询效率问题

    mybatis的查询效率问题

    1.配置信息

    现在有学生和老师两张表老师的Mapper

    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.1、关联查询时效率的问题---通过老师查找学生getById的形式

    配置文件:

    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映射文件:

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

    修改为:

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

    在进行查询的时候我们发现会只输出一句话;

    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进行映射

    2.2 关联查询别称起到的作用

    根据输出的内容我么还可以发现另外一些问题:
    1、通过自定义的sql语句进行查询时管理的查询出的对象没有null
    2、通过select的配置查询的记录是由null只出现的;
    关联查询别称起到的作用

    当我们吧select * from teacher这条语句进行替换成自定义的sql时;

    <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语句去完成查询

    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', '郝老师', '男', '无语', '五');
    
  • 相关阅读:
    Json解析
    Nopcommerce 使用Task时dbcontext关闭问题
    Webview离线功能(优先cache缓存+cache缓存管理)
    Android按钮单击事件的四种常用写法
    xUtils 源码解析
    返回键的复写onBackPressed()介绍
    GBK、GB2312和UTF-8编码区分
    Android 动画之RotateAnimation应用详解
    Android getWidth和getMeasuredWidth的区别
    WebView三个方法区别(解决乱码问题)
  • 原文地址:https://www.cnblogs.com/babyhhcsy/p/4497074.html
Copyright © 2011-2022 走看看