首页 > 其他分享 >Mybatis学习日志二

Mybatis学习日志二

时间:2023-03-15 23:33:43浏览次数:37  
标签:xml mapper 类型 name 学习 mybatis SQL Mybatis 日志

注意要点

  1. 全局配置文件中,各个标签要按照如下顺序进行配置,因为mybatis加载配置文件的源码中是按照这个顺序进行解析的

<configuration>
    <!-- 配置顺序如下
     properties  

     settings

     typeAliases

     typeHandlers

     objectFactory

     plugins

     environments
        environment
            transactionManager
            dataSource

     mappers
     -->
</configuration>

各个子标签说明如下

<properties>

一般将数据源的信息单独放在一个properties文件中,然后用这个标签引入,在下面environment标签中,就可以用${}占位符快速获取数据源的信息

<settings>

用来开启或关闭mybatis的一些特性,比如可以用<setting name="lazyLoadingEnabled" value="true"/>来开启延迟加载,可以用<settings name="cacheEnabled" value="true"/>来开启二级缓存

<typeAliases>

在mapper.xml中需要使用parameterType和resultType属性来配置SQL语句的输入参数类型和输出参数类型,类必须要写上全限定名,比如一个SQL的返回值映射为Student类,则resultType属性要写com.yogurt.po.Student,这太长了,所以可以用别名来简化书写,比如

<typeAliases>
    <typeAlias type="com.yogurt.po.Student" alias="student"/>
</typeAliases>

之后就可以在resultType上直接写student,mybatis会根据别名配置自动找到对应的类。

当然,如果想要一次性给某个包下的所有类设置别名,可以用如下的方式

<typeAliases>
   <package name="com.yogurt.po"/>
</typeAliases>

如此,指定包下的所有类,都会以简单类名的小写形式,作为它的别名

另外,对于基本的Java类型 -> 8大基本类型以及包装类,以及String类型,mybatis提供了默认的别名,别名为其简单类名的小写,比如原本需要写java.lang.String,其实可以简写为string

<typeHandlers>

用于处理Java类型和Jdbc类型之间的转换,mybatis有许多内置的TypeHandler,比如StringTypeHandler,会处理Java类型String和Jdbc类型CHAR和VARCHAR。这个标签用的不多

<objectFactory>

mybatis会根据resultType或resultMap的属性来将查询得到的结果封装成对应的Java类,它有一个默认的DefaultObjectFactory,用于创建对象实例,这个标签用的也不多

<plugins>

可以用来配置mybatis的插件,比如在开发中经常需要对查询结果进行分页,就需要用到pageHelper分页插件,这些插件就是通过这个标签进行配置的。在mybatis底层,运用了责任链模式+动态代理去实现插件的功能

<!-- PageHelper 分页插件 -->
<plugins>
  <plugin interceptor="com.github.pagehelper.PageInterceptor">
     <property name="helperDialect" value="mysql"/>
  </plugin>
</plugins>

<environments>

用来配置数据源

<mappers>

用来配置mapper.xml映射文件,这些xml文件里都是SQL语句

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}%'; 这条SQL最终就会变成

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>

 

 

 

上面其实是比较原始的开发方式,我们需要编写dao类,针对mapper.xml中的每个SQL标签,做一次封装,SQL标签的id要以字符串的形式传递给SqlSession的相关方法,容易出错,非常不方便;为了简化开发,mybatis提供了mapper接口代理的开发方式,不需要再编写dao类,只需要编写一个mapper接口,一个mapper的接口和一个mapper.xml相对应,只需要调用SqlSession对象上的getMapper(),传入mapper接口的class信息,即可获得一个mapper代理对象,直接调用mapper接口中的方法,即相当于调用mapper.xml中的各个SQL标签,此时就不需要指定SQL标签的id字符串了,mapper接口中的一个方法,就对应了mapper.xml中的一个SQL标签

基于Mapper代理的示例
全局配置文件和mapper.xml文件是最基本的配置,仍然需要。不过,这次我们不编写dao类,直接创建一个mapper接口

package com.yogurt.mapper;

import com.yogurt.po.Student;

import java.util.List;

public interface StudentMapper {

    List<Student> findAll();

    int insert(Student student);

    int delete(Integer id);

    List<Student> findByName(String value);
}

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语句的返回值类型一致

测试代码如下

public class MapperProxyTest {
    private SqlSessionFactory sqlSessionFactory;

    @Before
    public void init() throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    }

    @Test
    public void test() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
        List<Student> studentList = mapper.findAll();
        studentList.forEach(System.out::println);
    }
}

结果如下

 

 这个mapper接口,mybatis会自动找到对应的mapper.xml,然后对mapper接口使用动态代理的方式生成一个代理类

 

标签:xml,mapper,类型,name,学习,mybatis,SQL,Mybatis,日志
From: https://www.cnblogs.com/yzx-sir/p/17220663.html

相关文章

  • 使用 Filebeat 监听日志文件
    Filebeat是一个日志文件托运工具,在你的服务器上安装客户端后,filebeat会监控日志目录或者指定的日志文件,追踪读取这些文件(追踪文件的变化,不停的读),并且转发这些信息到elastic......
  • 【THM】Introductory Networking(网络基础介绍)-学习
    本文相关的TryHackMe实验房间链接:https://tryhackme.com/room/introtonetworking本文介绍:主要涉及网络基础理论、与网络相关的基本命令行工具的使用。简介本文将向初学......
  • 「AcWing学习记录」拓扑排序
    AcWing848.有向图的拓扑序列原题链接图的拓扑序列是针对有向图来说的,无向图是没有拓扑序列的。可以证明,有向无环图一定存在一个拓扑序列,所以有向无环图也被称为拓扑图......
  • 人工智能与机器学习速查表
    机器学习和深度学习库速查表Numpy库PandasScipyMatplotlibScikitLearnKerasNeuralNetworksZoo......
  • 阿里8年经验之谈,从功能测试进阶自动化测试,整理出这一份3000字超全学习指南
    最近收到不少小伙伴私信问,做了好几年测试,一直停留在手工测试点点点的阶段,想要进阶,想要做自动化测试,该怎么学习,以及需要学些什么? 今天,我就来聊一聊手工测试如何进阶......
  • c语言学习日志——练习
    T:实现一段字符串从两端逐个向中间移动。code:#define_CRT_SECURE_NO_WARNINGS#include<stdio.h>#include<string.h>intmain(){chararr1[]="Welcometo512";chara......
  • JSP学习笔记
    responsesendRedirect();重定向操作,使用后重新生成新的response(不能传递request对象)request.getRequestDispatcher("login.jsp").forward(request,response);getParamet......
  • 【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
    问题描述使用AzureKubernetes服务(AKS),可以通过kubectl连接pod中查看日志,但是如何来查看节点的系统日志呢?如是否有ubuntu系统升级的记录? 问题解答是的,可以进入AKS......
  • 有监督学习——支持向量机、朴素贝叶斯分类
    1.支持向量机支持向量机(SupportVectorMachine,SVM)最初被用来解决线性问题,加入核函数后能够解决非线性问题。主要优点是能适应小样本数量高维度特征的数据集,甚至是特......
  • MakeDown语法学习
    MarkDown学习二级标题三级标题四级标题字体hello,world!hello,world!hello,world!hello,world!引用选择狂神说java,走向人生巅峰分割线图片超链接链接跳转......