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 复制代码
<?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

xml 复制代码
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 复制代码
<?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 复制代码
<?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: 自定义字段名和属性名不一致时

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

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

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

会有SQL注入的风险 不推荐

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

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

xml 复制代码
<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注解的值为键

java 复制代码
// UserMapper接口里
User checkoutLogin(@Param("userName") String userName, @Param("password")String password);
// SqlSession
User user = mapper.checkoutLogin("mysql", "123456");
xml 复制代码
<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、模糊查询
xml 复制代码
select * from sys_user where user_name like "%"#{userName}"%"
5.2、批量删除

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

xml 复制代码
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、获取是自增主键的新增的数据
xml 复制代码
<!-- useGeneratedKeys: 标记当前sql操作的数据表,使用了自增主键 -->
<!-- keyProperty:值为数据表中的自增主键的的属性 -->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">

</insert>

6、MyBatis自定义映射resultMap

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

6.1、通过分步查表,解决多对一的属性字段映射关系
xml 复制代码
<!-- 多个员工对应一个部门  -->
<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、通过分步查询表,解决一对多的属性字段映射关系
xml 复制代码
<!-- 一个部门对应多个员工  -->
<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中

xml 复制代码
<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去掉, 只能去掉前面的

xml 复制代码
<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语句中

xml 复制代码
<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
xml 复制代码
<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的二级缓存【一级缓存是无法代替的】

相关推荐
郭小李11 小时前
mybatis 动态 sql
java·sql·mybatis
知守观12 小时前
技术考古:iBATIS 2.3.4 时代的持久层,是如何用 Map 玩转 307 个存储过程的?
java·后端·mybatis
captain37612 小时前
MyBatis Plus(1)
java·服务器·mybatis
代码不停18 小时前
MyBatis进阶
spring boot·mybatis
captain3761 天前
MyBatis(入门5)其他查询操作
java·数据库·spring boot·mybatis
captain3761 天前
MyBatis(进阶1)
mybatis
郭小李2 天前
mybatis的 Mapper.xml语法
xml·java·mybatis
m0_639906942 天前
MyBatis 实现分页查询|逻辑分页、物理分页、PageHelper 原理
mybatis
captain3762 天前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis
正儿八经的少年4 天前
MyBatis 一对一、一对多 SQL
数据库·sql·mybatis