Mybatis

什么是MyBatis?

  • MyBatis是一款优秀的持久化框架,用于简化JDBC开发。
  • MyBatis源于Apache的一个开源项目iBatis,2010年iBatis项目由Apache Software Foundation迁移到Google Code,并更名为MyBatis。

iBatis

  • iBatis一词源于internetabatis组合,是一个基于Java的持久层框架
  • iBatis提供的持久层框架包括SQL Maps和Data Access Objects(DAOs)

持久层

  • 持久层负责将数据保存到数据库这一层
  • JavaEE三层架构:表现层、业务层、持久层

数据持久化是将内存中的数据模型转换为存储模型,并将存储模型转换为内存中数据模型的统称。比如:文件的存储,数据的读取、数据表的增删改查等都是数据持久化操作。

框架

  • 框架是一个半成品软件,是一套可重用、通用的、软件基础代码模型。
  • 在框架的基础上构建软件时,编码会更加高效、规范、通用、可扩展。

MyBatis是一个半自动映射的框架,需手动匹配POJO和SQL的映射关系。MyBatis需手动编写SQL,因此灵活多变,支持动态SQL、处理列表、动态生成表名、支持存储过程,工作量相对较大。

JDBC缺点

  • 硬编码:注册驱动、获取连接、SQL语句...
  • 操作繁琐:手动设置参数、手动封装结果集...
MyBatis

资料

MyBatis是一个开源、轻量级的数据持久化框架,是JDBC和Hibernate的替代方案。

  • MyBatis避免了JDBC代码和手动设置参数、获取结果集。
  • MyBatis内部封装了JDBC,简化了加载驱动、创建连接、创建Statement等繁杂的过程,开发者只需关注SQL语句本身。
  • MyBatis使用XML或注解来配置和映射原生信息,将接口和Java的POJOs(Plain Ordinay Java Object,普通的Java对象)映射成数据库中的记录。

MyBatis支持定制化SQL、存储过程、高级映射,可以在实体类和SQL语句之间建立映射关系,是一种自动化的ORM实现。

MyBatis的核心思想是将程序中大量的SQL语句剥离出来,使用XML文件或注解的方式实现SQL的灵活配置,将SQL语句与程序代码分离,在不修改程序代码的情况下,直接在配置文件中修改SQL语句。

安装

  • 使用MyBatis前只需将mybatis.jar文件置于类路径classpath中即可
  • 若使用Maven构建项目则需在pom.xml文件中添加MyBatis的依赖代码。

快速入门

创建Maven模块导入MyBatis坐标

$ vim pom.xml
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>

添加MySQL数据库驱动的依赖包

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.30</version>
</dependency>

添加Lombok依赖

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>

添加日志相关依赖

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.2.11</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.11</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.36</version>
</dependency>

导入JUnit测试依赖

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

编写MyBatis核心配置文件

$ vim resources/mybatis-config.xml

替换JDBC连接信息参数,解决硬编码问题。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/fw"/>
                <property name="username" value="root"/>
                <property name="password" value="q7tkI4QvegrjUTCm"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="SysUserMapper.xml"/>
    </mappers>
</configuration>

创建数据表

CREATE TABLE `sys_user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `code` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '唯一编号',
  `created_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
  `created_by` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '创建人',
  `updated_at` datetime DEFAULT NULL COMMENT '更新时间',
  `updated_by` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '更新人',
  `username` varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '账户',
  `password` varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '密码',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户';

定义POJO类

$ vim pojo/SysUser.java
package com.jc.pojo;

import lombok.Data;
import java.util.Date;

@Data
public class SysUser {
    private Long id;
    private String code;
    private Date createdAt;
    private Date updatedAt;
    private String createdBy;
    private String updatedBy;

    private String username;
    private String password;
}

创建SQL映射文件,统一管理SQL语句,解决硬编码问题。

$ vim resources/SysUserMapper.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="sysUser">
    <select id="selectList" resultType="com.jc.pojo.SysUser">
        SELECT * FROM sys_user WHERE 1=1
    </select>
</mapper>
  • 加载核心配置文件,获取SqlSessionFactory对象。
  • 获取SqlSession对象执行SQL语句
  • 释放资源
$ vim app.java
public static void mybatis(){
    InputStream is = null;
    try {
        is = Resources.getResourceAsStream("mybatis-config.xml");
    } catch (IOException e) {
        e.printStackTrace();
    }

    SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
    SqlSession ss = ssf.openSession();

    List<SysUser> ll = ss.selectList("sysUser.selectList");
    System.out.println(ll);

    ss.close();
}

MyBatis包含一个名为Resources的工具类,它包含一些实用方法可从类路径或其它位置中加载资源文件。

InputStream is = Resources.getResourceAsStream("mybatis-config.xml");

每个MyBatis应用程序都使用了SqlSessionFactory实例,SqlSessionFactory实例可通过SqlSessionFactoryBuilder获得,SqlSessionFactoryBuilder可从XML配置文件或预定义配置类Configuration实例中获取。使用MyBatis后只需提供SQL语句,关注点可集中在SQL语句上。

SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);

IDEA中解决SQL映射文件的警告提示信息,由于IDEA和数据库没有建立连接,因此在XML中无法是被表信息,解决方案只需在IDEA中配置并连接数据库即可。

配置数据库连接

Mapper代理开发

MyBatis开发中会编写大量SQL到XML文件中,除了特殊的业务逻辑外,存在大量结构相似的增删改查的SQL。

使用Mapper代理开发的目的是为了解决原生方式中的硬编码,同时为了简化后期执行SQL。

Mapper的目的是为了解决单表增删改查,基于MyBatis插件开发者无需编写SQL,无需再DAO中增加方法,只需要编写好实体类,就能够支持相应的操作。

定义与SQL映射文件同名的Mapper接口

$ vim java/com/jc/mapper/SysUserMapper.java
package com.jc.mapper;

import com.jc.pojo.SysUser;
import java.util.List;

public interface SysUserMapper {
    List<SysUser> list();
}

将Mapper接口与SQL映射文件放置在同一目录下

$ vim resources/jc/com/mapper/SysUserMapper.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.jc.mapper.SysUserMapper">
    <select id="list" resultType="com.jc.pojo.SysUser">
        SELECT * FROM sys_user WHERE 1=1
    </select>
</mapper>

设置SQL映射文件的namespace属性值为Mapper接口全限定名

namespace="com.jc.mapper.SysUserMapper"

在Mapper接口中定义方法,方法名为SQL映射文件中SQL语句的id属性,同时保持参数类型和返回值一致。

List<SysUser> list();

如果Mapper接口名与SQL映射文件名相同,并在同一目录下则可使用包扫描方式来简化SQL映射文件的加载。

$ vim resources/mybatis-config.xml
<mappers>
<!--        <mapper resource="com/jc/mapper/SysUserMapper.xml"/>-->
    <package name="com.jc.mapper" />
</mappers>

编码流程

  1. 通过SqlSession的getMapper()方法获取Mapper接口中的代理对象
InputStream is = null;
try {
    is = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
    e.printStackTrace();
}

SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
SqlSession ss = ssf.openSession();

SysUserMapper m = ss.getMapper(SysUserMapper.class);
List<SysUser> l = m.list();
System.out.println(l);

ss.close();

openSession()默认接收名为autoCommit的布尔值用于设置自动提交事务,默认不填为false,表示关闭事务自动提交,因此在DML语句执行时需手工提交事务。

  1. 调用对应方法完成SQL的执行
SysUserMapper m = ss.getMapper(SysUserMapper.class);
List<SysUser> l = m.list();
System.out.println(l);

核心配置

  • 配置标签时需遵循前后顺序
$ vim resources/mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/fw"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
    <!--        <mapper resource="com/jc/mapper/SysUserMapper.xml"/>-->
        <package name="com.jc.mapper" />
    </mappers>
</configuration>

类型别名typeAliases

添加类型别名可为Java类型设置一个缩写名字,仅用于XML配置,目的在于降低冗余的全限定类名的书写。

$ vim resources/mybatis-config.xml
<configuration>
    <typeAliases>
        <package name="com.jc.pojo" />
    </typeAliases>
</configuration>

配置类型别名后,可直接简化SQL映射文件中resultType中的之前全限定类名。

$ vim resources\com\jc\mapper\SysUserMapper.xml
<mapper namespace="com.jc.mapper.SysUserMapper">
    <select id="list" resultType="SysUser">
        SELECT * FROM sys_user WHERE 1=1
    </select>
</mapper>

需要注意的是如果数据库表的名称和POJO实体类的属性名称不一致则不能自动封装数据,解决的方法有两种:

  • 起别名:对不一样的列名起别名,让别名和实体类的属性名保持一致。
<mapper namespace="com.jc.mapper.SysUserMapper">
    <select id="list" resultType="SysUser">
        SELECT id, created_at AS createdAt, created_by AS createdBy FROM sys_user WHERE 1=1
    </select>
</mapper>

起别名的缺点在于每次查询都要定义一次别名,解决方案可采用SQL片段的方式,但SQL片段的方式也不够灵活。

<mapper namespace="com.jc.mapper.SysUserMapper">
    <sql id="column">
        id, created_at AS createdAt, created_by AS createdBy
    </sql>
    <select id="list" resultType="SysUser">
        SELECT
        <include refid="column" />
        FROM sys_user WHERE 1=1;
    </select>
</mapper>
  • resultMap:定义<resultMap>标签完成不一致的属性名和列名的映射
<mapper namespace="com.jc.mapper.SysUserMapper">
    <resultMap id="resultMap" type="SysUser">
        <id column="id" property="id" />
        <result column="code" property="code" />
        <result column="created_at" property="createdAt" />
        <result column="created_by" property="createdBy" />
    </resultMap>
    <sql id="column">
        id, code, created_at, created_by
    </sql>
    <select id="list" resultMap="resultMap">
        SELECT
        <include refid="column" />
        FROM sys_user WHERE 1=1;
    </select>
</mapper>

MyBatisX

MyBatisX是一款基于IDEA的快速开发插件,为效率而生。

主要功能

  • 实现XML与接口方法相互跳转
  • 根据接口方法生成Statement
MyBatisX

增删改查

主键查询

public interface SysUserMapper {
    SysUser getById(long id);
}
<mapper namespace="com.jc.mapper.SysUserMapper">
    <select id="getById" resultType="SysUser" parameterType="long">
        SELECT * FROM sys_user WHERE 1=1 AND id=#{id}
    </select>
</mapper>
参数占位符说明
#{}将所占据位置替换为?号,为防止SQL注入而设置的预处理语句。
${}直接替换,有SQL注入风险。当表名或列名不固定的情况下可使用。

参数类型:可省略

parameterType="long"

特殊字符处理

  • 使用转义字符
<select id="getById" resultType="SysUser" parameterType="long">
    SELECT * FROM sys_user WHERE 1=1 AND id &lt; #{id}
</select>
  • 使用CDATA区
<select id="getById" resultType="SysUser" parameterType="long">
    SELECT * FROM sys_user WHERE 1=1 AND id <![CDATA[<]]> #{id}
</select>

条件查询

接收参数三种方式

设置参数说明
散装参数使用@Param("SQL中的参数占位符名称")
实体类封装参数只需保证SQL中参数名和实体类属性名对应即可
Map集合只需保证SQL中参数名和Map集合键名对应即可

例如:多条件查询

List<SysUser> list(Map m);
List<SysUser> list(SysUser d);
List<SysUser> list(@Param("id") Long id, @Param("username") String username);

SQL语句需要随着用户输入或外部条件的变化而变化,即动态SQL。

<select id="list" resultMap="resultMap">
    SELECT * FROM sys_user WHERE 1=1
    <if test="id != null">AND id = #{id}</if>
    <if test="username != null">AND username LIKE #{username}</if>
</select>

注意LIKE模糊匹配时需预先对参数值username处理

username=%+username+%

MyBatis对动态SQL提供支持

标签说明
if条件判断
choose(when, otherwise)从多个条件选择一个
trim(where, set)截取
foreach遍历循环

添加数据

  • 提交事务
  • 主键返回
int add(SysUser d);
<insert id="add" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_user(
    created_at
    <if test="username != null">,username</if>
    <if test="password != null">,password</if>
) VALUES (
    NOW()
    <if test="username != null">,#{username}</if>
    <if test="password != null">,MD5(#{password})</if>
)
</insert>

测试获取添加后的主键

InputStream is = null;
try {
    is = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
    e.printStackTrace();
}

SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
SqlSession ss = ssf.openSession();

SysUserMapper m = ss.getMapper(SysUserMapper.class);

SysUser d = new SysUser();
d.setUsername("root");
if(m.add(d) > 0){
    System.out.println(d.getId());
}

ss.commit();
ss.close();

修改数据

  • 修改全部字段
  • 修改全部字段
int edit(SysUser d);
<update id="edit">
    UPDATE sys_user
    <set>
        updated_at=NOW()
        <if test="username != null">,username = #{username}</if>
        <if test="password != null">,password = MD5(#{password})</if>
    </set>
    <where>
        <if test="id != null">AND id = #{id}</if>
        <if test="username != null">AND username = #{username}</if>
    </where>
</update>
InputStream is = null;
try {
    is = Resources.getResourceAsStream("mybatis-config.xml");
} catch (IOException e) {
    e.printStackTrace();
}

SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(is);
SqlSession ss = ssf.openSession();

SysUserMapper m = ss.getMapper(SysUserMapper.class);

SysUser d = new SysUser();
d.setId(1L);
d.setPassword("root");
if(m.edit(d) > 0){
    System.out.println(d.getId());
}

ss.commit();
ss.close();

删除数据

  • 删除单条
int delById(long id);
<delete id="delById">
    DELETE FROM sys_user
    <where>
        <if test="id != null">id=#{id}</if>
    </where>
</delete>
  • 批量删除
int delByIds(@Param("ids") long[] ids);
<delete id="delByIds">
    DELETE FROM sys_user
    <where>
        id IN
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </where>
</delete>

参数传递

MyBatis接口方法可接收各种类型的参数,底层对这些参数进行不同的封装处理。

  • MyBatis接口接收单个参数的类型包括POJO、Map、Collection、List、Array...
单个参数说明
POJO直接使用,属性名和参数占位符名称必须保持一致。
Map直接使用,键名和参数占位符名称必须保持一致。
Collection会封装成为Map,可使用@Param注解。
  • MyBatis接口接收多个参数时需使用@Param注解

当使用多个参数传递时,MyBatis会将多个参数封装成为一个Map集合,MyBatis底层提供了ParamNameResolver类进行参数封装,使用@Param注解时会替换Map集合中默认的键名。

建议参数传递时使用@Param注解来修改Map集合中默认的键名,并使用修改后的名称来获取值,这样可读性更高。

分层架构

分层描述
API接口层提供给外部使用的接口API
数据处理层负责具体的SQL查询、解析、执行、结果映射处理,目的是根据调用的请求完成依次数据库操作。
基础支撑层负责最基础的功能支撑,包括连接管理、事务管理、配置加载、缓存处理。
MyBatis

框架架构

步骤名称描述
1加载配置将SQL配置信息加载成一个个的MappedStatement对象并存储到内存
2SQL解析API接口成接收到调用请求时,接收到传入SQL的ID和对象,根据ID找到对应的MapperStatement,在根据入参对象对MapperStatement解析,解析后获得最终要执行的SQL语句和参数。
3SQL执行将最终得到的SQL和参数拿到数据库进行执行,获得操作数据库的结果。
4结果映射将操作数据库的结果按映射配置进行转换

执行流程

处理操作请求过程

  1. 根据SQL的ID查找对应的MappedStatement对象
  2. 根据传入参数对象解析MappedStatement对象,最终得到要执行的SQL和执行传入参数。
  3. 获取数据库连接,根据得到的最终SQL语句和执行传入参数到数据库执行,并得到执行结果。
  4. 根据MappedStatement对象中的结果映射配置,对得到的执行结果进行转换处理,并得到最终的处理结果。
  5. 释放连接资源

操作流程

  1. 加载配置并初始化
项目说明
触发条件加载配置文件
处理过程将SQL配置信息加载成为一个一个的MapperStatement对象(包括传入参数映射配置、执行的SQL语句、结果映射配置),存储到内存中。

配置来源两个地方:配置文件、Java代码注解

  1. 接收调用请求
项目说明
触发条件调用MyBatis提供的API
传入参数为SQL的ID和传入参数对象
处理过程将请求传递给下层(请求处理层)进行处理
  1. 处理操作请求
项目说明
触发条件API接口层传递请求过来
传入参数为SQL的ID和传入参数对象
  1. 返回处理结果

注解开发

使用注解开发会比配置文件更加方便,注解适用于简单查询,对于复杂查询依然使用XML配置文件的方式。

注解说明
@Select查询
@Insert添加
@Update修改
@Delete删除

@Mapper

@Mapper注解是由MyBatis框架定义的一个描述数据层接口的注解(描述性作用)。

@Mapper用于告知SpringBoot框架此接口的实现类是由MyBatis负责创建,并将其实现类对象存储到Spring容器中进行管理。

@Mapper
public interface SysDictTypeMapper

SSM项目中大量配置文件的读写,可通过注解的方式来简化操作。对于DAO接口层的配置可通过@mapper注解来实现。

若直接在Mapper接口类中添加@Mapper注解,需在每个Mapper接口类都添加@Mapper注解,相对较为繁琐。

@Mapper的作用是给Mapper接口自动生成一个实现类,让Spring对Mapper接口的Bean进行管理,省略较为复杂的XML文件。

@Mapper注解是MyBatis自动配置时,默认扫描的注解类。

@MapperScan

通过@MapperScan可指定需要扫描的Mapper接口类的包路径,在路径中可使用*作为通配符对包名进行匹配。也可使用@MapperScan注解对多个包进行扫描。

Spring集成

当MyBatis与依赖注入框架注入Spring、Guice等同时使用时,SqlSession将会被依赖注入框架所创建,因此无需使用SqlSessionFactoryBuilderSqlSessionFactory

MyBatis
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值