Bootstrap

SSM之Mybatis

SSM之Mybatis

一、MyBatis简介

实现了操作数据库的JDBC的封装。

1、MyBatis特性

  • 持久层框架,支持定制化SQL、存储过程以及高级映射;
  • 封装了JDBC以及获取结果集代码
  • 可以使用XML或者注解用于配置原始映射,映射成数据库中的记录
  • 半自动的ORM(对象关系映射)框架(SQL需要自己写)

2、MyBatis的下载

mybatis的jar包,可以通过maven下载,gihub可以拿到mybatis的官方文档

3、MyBatis和其他持久化层技术对比

在这里插入图片描述

MyBatis下载

Hibernate是全自动的:不需要写SQL语句
MyBatis是半自动的:需要写SQL语句

二、MyBatis框架搭建

第一步:new Module

在这里插入图片描述
在这里插入图片描述

第二步:在pom.xml中导入依赖jar包

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zhw.mybatis</groupId>
    <artifactId>mybatis2</artifactId>
    <version>1.0-SNAPSHOT</version>
    <!-- 设置工程的打包方式  -->
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <!-- 导入工程依赖  -->
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
             <!-- mysql依赖版本要和本地安装的mysql版本一样/或者兼容  -->
            <version>8.0.31</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!--        <dependency>-->
        <!--            <groupId>log4j</groupId>-->
        <!--            <artifactId>log4j</artifactId>-->
        <!--            <version>1.2.12</version>-->
        <!--        </dependency>-->
    </dependencies>
</project>

第三步:创建mybatis的核心配置文件 resources/mybatis-config.xml

第四步: 创建mybatis的映射文件 resources/com/zhw/mybatis/mapper/*.xml

三、MyBatis基础功能

1、MyBatis核心配置文件 /resources/mybatis-config.xml

jdbc.properties

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/zhw_blog?useSSL=false&serverTimezone=Hongkong&characterEncoding=utf-8&autoReconnect=true
jdbc.username=root
jdbc.password=
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
	<!--
		标签顺序必须按照如下顺序 错了会报错
		properties?,
		settings?,
		typeAliases?,
		typeHandlers?,
		objectFactory?,
		objectWrapperFactory?,
		reflectorFactory?,
		plugins?,
		environments?,
		databaseIdProvider?,
		mappers?
	-->
	<!--引入properties文件  数据库连接配置抽离出到同级下的jdbc.properties-->
    <properties resource="jdbc.properties" />
    <!--设置mybatis的全局配置-->
    <settings>
    	<!--设置实体类的驼峰命名和数据库的下划线命名对应-->
        <setting name="mapUnderscoreToCamelCase" value="true" />
        <!-- 开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>
    <typeAliases>
		<!-- <typeAlias type="com.zhw.mybatis.pojo.User" alias="User" />-->
		<!-- 以包为单位 将包下所有的类设置为别名为类名  且不区分大小写 -->
        <package name="com.zhw.mybatis.pojo"/>
    </typeAliases>
    <!-- environments: 配置多个连接数据库的环境
    		default:根据环境id 设置默认使用哪个数据库环境
    -->
    <environments default="development">
        <environment id="development">
        	<!-- 
        		transactionManager: 设置事务管理方式
        		type: JDBC/MANAGED
        			JDBC: 表示当前环境中,执行SQL时,使用的是JDBC中原生的事务管理方式,即是:事务的提交或者回滚需要手动处理;
        			MANAGED: 被管理。例如spring中的AOP
        	-->
            <transactionManager type="JDBC"/>
            <!-- 
        		dataSource: 设置数据源
        		type: POOLED/UNPOOLED/JNDI
        			POOLED: 表示使用数据库连接池缓存数据库连接
        			UNPOOLED: 不使用数据库连接池
        			JNDI: 表示使用上下文中的数据源
        	-->
            <dataSource type="POOLED">
            	<!-- 数据库驱动-->
                <property name="driver" value="${jdbc.driver}"/>
                <!-- 数据库地址-->
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
    	<!-- <mapper resource="mappers/UserMapper.xml"/> -->
        <!--
            以包为单位引入映射文件:  多级目录的创建    com/zhw/mybatis/mapper
            要求:
                1、mapper接口所在包要和映射文件所在包一致【层次和名字】
                2、mapper接口要和映射文件的名字一致
         -->
       <package name="com.zhw.mybatis.mapper"/>
    </mappers>

</configuration>

2、MyBatis映射文件

<?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">
        namespace
<!--namespace: mapper接口所在的全类名-->
<mapper namespace="com.zhw.mybatis.mapper.UserMapper">
	<!--selectUser: mapper接口里的抽象方法-->
    <select id="selectUser" resultType="com.zhw.mybatis.pojo.User">
        select * from sys_user where id = 1
    </select>
</mapper>

3、MyBatis实现增删改查

在这里插入图片描述
查: 需要指定resultType 实体类型
resultMap: 自定义字段名和属性名不一致时
在这里插入图片描述

 <select id="selectUser" resultType="实体类型对象全类名">
   select * from sys_user where id = 1
</select>

4、MyBatis获取参数值的两种方式

1、${} 本质字符串拼接【需要程序员手动添加单引号】

会有SQL注入的风险 不推荐

<select id="getUserByUserName" resultType="User">
      select * from sys_user where del_flag = 0 and user_name = '${userName}'     // 【需要程序员手动添加单引号】
 </select>

2、#{} 本质占位符赋值,会默认加单引号

<select id="getUserByUserName" resultType="User">
      select * from sys_user where del_flag = 0 and user_name = #{userName}    
 </select>

3、mybatis获取参数值的各种情况

3.4、实参是实体类

传递的是实体类,直接通过属性名占位获取

3.1、通过@param注解命名参数

传的是String, mapperXml接收的是Map集合,且是 以@param注解的值为键

// UserMapper接口里
User checkoutLogin(@Param("userName") String userName, @Param("password")String password);
// SqlSession
User user = mapper.checkoutLogin("mysql", "123456");
<select id="checkoutLogin" resultType="User">
    select * from sys_user where del_flag = 0 and user_name = #{userName} and password = #{password}
</select>

5、MyBatis执行特殊SQL语句

5.1、模糊查询
select * from sys_user where user_name like "%"#{userName}"%"
5.2、批量删除

批量删除不能使用#{}. 因为#{}会默认添加单引号,从而导致批量删除SQL语句报错

delete from sys_user where id in (${ids})
delete from sys_user where id in (1,2,3) // 对
delete from sys_user where id in ('1,2,3') // 错误
5.3、获取是自增主键的新增的数据
<!-- useGeneratedKeys: 标记当前sql操作的数据表,使用了自增主键 -->
<!-- keyProperty:值为数据表中的自增主键的的属性 -->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">

</insert>

6、MyBatis自定义映射resultMap

分步查询的优点:可以实现延迟加载(即是分步时,可以只是获取其中一个表的数据,关联表的数据不获取)

6.1、通过分步查表,解决多对一的属性字段映射关系
<!-- 多个员工对应一个部门  -->
<resultMap id="deptMap" type="Employee">
    <id property="id" column="id"></id>
    <result property="userName" column="user_name"></result>
    <result property="password" column="password"></result>
    <!-- select:分步查询sql的唯一标识namespace.SQLId  / mapper接口的全类名.方法名 -->
    <!-- column:分步查询sql的条件 -->
    <!-- fetchType: 当开启了全局延迟加载后,可以通过该属性控制延迟加载的效果 -->
    <association property="dept"
                 select="com.zhw.mybatis.mapper.SelectMapper.getAllUser"
                 column="dept_id"
                 fetchType="lazy"
                 ></association>
</resultMap>
6.2、通过分步查询表,解决一对多的属性字段映射关系
<!-- 一个部门对应多个员工  -->
<resultMap id="deptMap" type="Dept">
    <id property="id" column="id"></id>
    <result property="userName" column="user_name"></result>
    <result property="password" column="password"></result>
    <association property="emps"
                 select="com.zhw.mybatis.mapper.SelectMapper.getAllUser"
                 column="dept_id"
                 fetchType="lazy"
                 ></association>
</resultMap>

7、MyBatis的动态Sql

使用xml标签,根据不同条件,拼接sql语句

7.1、if标签

if标签中的test属性所对应的表达式决定标签中的内容是否需要拼接到SQL中

<select id="selectUserByParams" resultType="User">
  # 1 = 1: 恒成立条件  为了拼接后面的and条件,避免某个为空造成的SQL语法错误
   select * from sys_user where 1 = 1
   <if test="userName != null and userName != ''">
       and user_name = #{userName}
   </if>
   <if test="password != null password age != ''">
       and password = #{password}
   </if>
</select>
7.2、where标签

当where标签中有内容时,会自动生成where关键字,并且将sql语句前多余的and或者or去掉
当where标签中没有内容时,此时where不会解析到SQL语句中
注意: where标签不能将sql语句后面多余的and或者or去掉, 只能去掉前面的

<select id="selectUserByParams" resultType="User">
select * from sys_user
<where>
   <if test="userName != null and userName != ''">
       and user_name = #{userName}
   </if>
   <if test="password != null password age != ''">
       or password = #{password}
   </if>
</where>
</select>
7.3、trim标签

当trim标签中有内容时:
prefix|suffix: 将拼接语句的前面或者后面添加指定内容
suffixOverrides|prefixOverrides:将拼接的sql语句中的前面后面指定的内容去掉
当trim标签中没有内容时,trim标签无任何效果,即是不会被解析到sql语句中

<select id="selectUserByParams" resultType="User">
   select * from sys_user
   <trim prefix="where" suffixOverrides="and|or">
       <if test="userName != null and userName != ''">
           and user_name = #{userName}
       </if>
       <if test="password != null password age != ''">
           and password = #{password}
       </if>
   </trim>
</select>
7.4、choose、when、otherwise 相当于 if…else if…else
<select id="selectUserByParams" resultType="User">
   select * from sys_user
   <where>
        <choose>
            <when test="userName != null and userName != ''">
                user_name = #{userName}
            </when>
            <when test="password != null and password != ''">
                password = #{password}
            </when>
            <otherwise></otherwise>
        </choose>
   </where>
</select>
7.5、foreach标签

根据or关键字或者in关键字,接收数组,批量删除
在这里插入图片描述
批量新增数据
在这里插入图片描述

7.6、sql标签:存储sql片段

在这里插入图片描述

四、MyBatis的分页插件

五、MyBatis的逆向工程

通过配置插件将数据库表逆向的映射成实体类、mapper配置和mapper接口

六、MyBatis的缓存

缓存只针对查询操作

1、mybatis的一级缓存

mybatis的一级缓存是默认开启的,级别是SqlSession。同一个SqlSession的相同查询条件,只会执行一次SQL语句,后面都会从缓存中获取的,不会再次访问数据库的。

1.1、使一级缓存失效的四种情况
  1. 不同的SqlSession对应不同的一级缓存
  2. 同一个SqlSession但是查询条件不同
  3. 同一个SqlSession两次查询期间执行了任何一次的增删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存。sqlSession.clearCache()

2、mybatis的二级缓存

mybatis的二级缓存是默认关闭的。级别是SqlSessionFactory,比一级缓存的级别大。即是:通过同一个SqlSessionFactory创建的sqlSession查询的都会被缓存

2.1 、二级缓存开启的必须条件,缺一不可
  1. 在核心配置文件中,设置全局配置属性cacheEnabled=“true”,默认为true,所以不需要手动设置了
  2. 在映射文件中设置标签
  3. 必须手动关闭/提交sqlSession
  4. 需要缓存的实体类必须实现序列化接口
2.2、 二级缓存失效情况
  1. 两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
2.3、二级缓存cache标签的配置

在这里插入图片描述

2.4、mybatis缓存查询顺序:

在这里插入图片描述

3、整合第三方缓存EHCache,代替mybatis的二级缓存【一级缓存是无法代替的】

;