Mybatis高频面试题

Mybatis高频面试题

上篇文章讲述了Spring如何配置Mybatis环境。

SpringBoot配置Mybatis:详细易懂

本篇文章主要介绍Mybatis的一些高频面试知识点。持续更新。希望点个收藏

#{}、${}区别

网上标准答案:#{}是预编译处理,${ } 是字符串替换。

Mybatis在处理#{}时,会将sql语句中的#{}替换成?号。调用PreparedStatement的set方法来赋值Mybatis在处理${}时,就是把${}替换成变量的值。使用#{}可以有效防止SQL注入,提高系统安全性

答案肯定是对的,但是大部分人简单看完,对防止SQL注入的原理还是一知半解。下面举个实例加深理解

-- 针对此条Sql语句. 网站登入验证SQL语句
 -- name = "1' OR '1'='1"
 -- passWord = "1' OR '1'='1"
select * from user where name = #{name} and passwrod = #{password};

-- #{} 分两步
-- 第一步 替换成一下sql,进行预编译
select * from user where name = ? and password = ?;
PreparedStatement pstatement = conn.prepareStatement(sql);
-- 第二步 PreparedStatement的set方法替换,执行sql
pstmt.setString(1, name); 
pstmt.setString(2, password);
ResultSet rs=pstmt.executeUpdate(); 

-- ${} 直接替换
select * from user where name = ${name} and password = ${password};
-- 替换后
 select * from user where name ='1' or '1' = '1' and password = '1' or '1' = '1';
 -- 等同于
 select * from user;
-- 在后台帐号验证的时候巧妙地绕过了检验,达到无账号密码,亦可登录网站。所以SQL注入攻击被俗称为黑客的填空游戏。

延迟加载

官方答案:Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。

看完,大多数人只有一个概念,延迟加载是什么估计都没有明白

我先用sql知识解释一下延迟加载,然后,在mybatis环境下实验

原理解析

关联查询:是一个多表连接查询,设计到join操作,不如单表查询快速

-- Student表属性列:Sno, Sname, Sage;
-- SC表属性列: Sno, Cno;
-- 查询选了课的学生名字,关联查询
select Sno, Cno, Sname from sc, student where sc.Sno = student.Sno;
-- 其实可以拆分成两个单表查询
select Sno, Cno from SC;
select Sname from student where Sno = #{第一个查询结果Sno}

延迟加载原理就是将关联查询分解成两个单表查询,首先执行第一个单表查询,当有需要时,再进行第二个单表查询。

实例实验

前期准备:

  • 在MySQL数据库中创建两个表,一个学生表,一个选课表,并插入数据

  • 创建两个bean类,对应表的属性列

  package com.test.demo;
  
  public class Student {
      public int sNo;
      public String sName;
      public int sAge;
      public Student(int sNo, String sName, int sAge) {
          this.sNo = sNo;
          this.sName = sName;
          this.sAge = sAge;
      }
      //getter、setter方法此处省略
  }
package com.test.demo;
public class SC {
    Student student;
    int cNo;
	//getter、setter方法省略
}

创建接口和xml文件:

package com.test.demo.mapper;
import java.util.List;
import com.test.demo.Student;

public interface StudentMapper {
    void insert(Student student);
    void delete(String sNo);
    Student selectByNumber(Integer sNo);
    void updateName(Student student);
    List<Student> findByCondition(String sName, Integer sAge);
    List<Student> selectByNumberList(List<Integer> list);
}
package com.test.demo.mapper;

import com.test.demo.SC;
import java.util.List;
public interface SCMapper {
    List<SC> selectByNumber(Integer cNo);
}

XML文件重点

studentMapper文件

<?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.test.demo.mapper.StudentMapper">
    <select id="selectByNumber" parameterType="java.lang.Integer" resultType="com.test.demo.Student">
        SELECT * FROM student where Sno = #{sNo}
    </select>
</mapper>

scMapper文件

<mapper namespace = "com.test.demo.mapper.SCMapper">
    <select id="selectByNumber" parameterType="java.lang.Integer" resultMap="lazyMap">
        SELECT * FROM sc where Cno = #{cNo}
    </select>
	<!--property:需要延迟加载的属性-->
    <!--javaType:属性类型-->
    <!--select:延迟加载需要执行的sql语句-->
    <!--column:关联查询的属性列-->
    <resultMap id="lazyMap" type="com.test.demo.SC">
        <association property="student" javaType="com.test.demo.Student" select="com.test.demo.mapper.StudentMapper.selectByNumber" column="Sno">
        </association>
    </resultMap>
</mapper>

main方法

List<SC> scList = scMapper.selectByNumber(4);
for(SC sc : scList) {
    //延迟加载
    Student student = sc.getStudent();
    System.out.println(student.getSName());
}

二级缓存

  • 一级缓存

    默认开启一级缓存,一级缓存的作用范围是SqlSession。如果执行的sql语句,SqlSession以前执行过,直接会复用缓存的结果,而不会去数据库查询。调用SqlSession的closeclearCache方法或者执行SQL语句是update、delete、insert,都会更新一级缓存

  • 二级缓存

    二级缓存向胆固全局缓存,默认不开启,可以再配置文件中开启,并且要求POJO实现Serializable接口,即必须可序列化。

    • select语句的返回结果均会被缓存
    • insert、update、delete语句会刷新缓存
    • 使用LRU算法进行缓存替换

参考文章

#{}与${}的区别

延迟加载(mybatis笔记)

mybatis的一级和二级缓存详细介

发布了206 篇原创文章 · 获赞 713 · 访问量 17万+

猜你喜欢

转载自blog.csdn.net/zycxnanwang/article/details/105685167