总结一下毕设中主要技术(8)

149 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

mapper.xml的SQL语句中的占位符${}和#{}

一般会采用#{},#{}在mybatis中,最后会被解析为?,其实就是Jdbc的PreparedStatement中的?占位符,它有预编译的过程,会对输入参数进行类型解析(如果入参是String类型,设置参数时会自动加上引号),可以防止SQL注入,如果parameterType属性指定的入参类型是简单类型的话(简单类型指的是8种java原始类型再加一个String),#{}中的变量名可以任意,如果入参类型是pojo,比如是Student类

public class Student{ 
    private String name; 
    private Integer age; 
    //setter/getter 
}

那么#{name}表示取入参对象 Student 中的 name 属性,#{age}表示取age属性,这个过程是通过反射来做的,这不同于${}${}取对象的属性使用的是 OGNL(Object Graph Navigation Language) 表达式

${},一般会用在模糊查询的情景,比如SELECT * FROM student WHERE name like '%${name}%';

它的处理阶段在#{}之前,它不会做参数类型解析,而仅仅是做了字符串的拼接,若入参的 Student 对象的name属性为zhangsan,则上面那条 SQL 最终被解析为SELECT * FROM student WHERE name like '%zhangsan%';

而如果此时用的是SELECT * FROM student WHERE name like '%#{name}%'; 这条 SQ L最终就会变成

SELECT * FROM student WHERE name like '%'zhangsan'%'; 所以模糊查询只能用${},虽然普通的入参也可以用${},但由于${}不会做类型解析,就存在 SQL注入 的风险,比如

SELECT * FROM user WHERE name = '${name}' AND password = '${password}'

我可以让一个user对象的password属性为'OR '1' = '1,最终的 SQL 就变成了

SELECT * FROM user WHERE name = 'yogurt' AND password = ''OR '1' = '1',因为OR '1' = '1'恒成立,这样攻击者在不需要知道用户名和密码的情况下,也能够完成登录验证

另外,对于 pojo 的入参,${}中获取对象属性的语法和#{}几乎一样,但${}在 mybatis 底层是通过 OGNL 表达式语言进行处理的,这跟#{}的反射处理有所不同

对于简单类型(8种java原始类型再加一个String)的入参,${}中参数的名字必须是value,例子如下

<select id="fuzzyCount" parameterType="string" resultType="int"> 
    SELECT count(1) FROM `user` WHERE name like '%${value}%' 
</select>

结合 Mapper 实现

  1. 创建 Mapper 接口类;
  2. 创建 Mapper 的 xml 文件
<?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.yogurt.mapper.StudentMapper">
    <select id="findAll" resultType="com.yogurt.po.Student">
        SELECT * FROM student;
    </select>

    <insert id="insert" parameterType="com.yogurt.po.Student">
        INSERT INTO student (name,score,age,gender) VALUES (#{name},#{score},#{age},#{gender});
    </insert>

    <delete id="delete" parameterType="int">
        DELETE FROM student WHERE id = #{id};
    </delete>

    <select id="findByName" parameterType="string" resultType="student">
        SELECT * FROM student WHERE name like '%${value}%';
    </select>
</mapper>

mapper接口和mapper.xml之间需要遵循一定规则,才能成功的让mybatis将mapper接口和mapper.xml绑定起来

  1. mapper接口的全限定名,要和mapper.xml的namespace属性一致;
  2. mapper接口中的方法名要和mapper.xml中的SQL标签的id一致;
  3. mapper接口中的方法入参类型,要和mapper.xml中SQL语句的入参类型一致;
  4. mapper接口中的方法出参类型,要和mapper.xml中SQL语句的返回值类型一致;

Mybatis 工具类

  1. 先 new 一个 SqlSessionFactoryBuilder(),得到一个返回值 builder;
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
  1. 获取我们的 SqlSessionFactory,要用builder.上我们的 builder() 方法,通过流的形式传一个In的参数;
  2. 通过 Resources.getResourceAsStream("") 读取我们的主配置文件才能调用我们的依赖信息,在这里抛异常。这里有一个返回值 nputStream in(字节流),通过字节流就可以读取;
  3. 这时 builder.build(in) ;得到哟个返回值就是 SqlSessionFactory factory;
  4. 得到 SqlSessionFactory factory 之后,根据图片的流程就要得到我们的 SqlSession;
  5. factory.openSession() 打开我们的 Session,就可以得到我们的 Session;
  6. 执行 sql 语句。sqlSession.getMapper(这里的 mapper 利用的是我们的一个反射机制,机制利用的时我们的一个接口)通过 sqlSession.getMapper(PersonMapper.class) 调用一个调用方法,得到一个返回值 count;
  7. 输出对应的返回值;
  8. 关闭 sqlsession;

关于 Mybatis 就通过这两篇博客介绍完毕了,答辩现场反正也没多长时间介绍,把自己知道的都说出来就好。
有错误请指正
我向你敬礼啊,Salute!