MyBatis与其使用方法讲解

在讲解Mybatis之前,我们需了解一个概念ORM(Object-Relational Mapping)对象关系映射,其是数据库与Java对象进行映射的一个技术.通过使用ORM,我们可以不用编写负责的Sql语句,而是通过操作对象来实现增删改查操作

缺优分析

  • 优点提高开发效率,减少代码的重复性和维护成本增加代码的可读性,降低复杂度对数据库查询的细节进行抽象,隐藏了sql语句
  • 缺点在进行多表联查时,或存在where条件时,ORM语句会变得复杂

MyBatis

  • mybatis是一个支持自定义SQL的持久层框架,通过XML文件来实现SQL配置和数据映射,MyBatis允许开发者手动编写SQL语句,提高灵活性

Mybatis通过**mapper**文件,将sql查询和Java对象绑定到一起,简化了JDBC代码的编写,手动设置参数,获取结果集的工作

MyBatis的工作流程

  • 其分为以下几步

MyBatis的基本使用

环境准备

  • 引入依赖包:
xml 复制代码
<!--springboot的mybatis >
<dependency>    
		<groupId>org.mybatis.spring.boot</groupId>    
		<artifactId>mybatis-spring-boot-starter</artifactId>   
		<version>3.0.3</version>
</dependency>

<!-- MySQL 连接器 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.23</version>
</dependency>
  • 创建mybatis配置文件(mybatis-config.xml)
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>
    <!-- mybatis环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <!-- 配置事务的类型 -->
            <transactionManager type="JDBC"></transactionManager>
            <!-- 配置数据源(连接池) -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/数据库名称?userSSL=false&amp;serverTimezone=Asia/Shanghai"/>
                <property name="username" value="帐号"/>
                <property name="password" value="密码"/>
            </dataSource>
        </environment>
    </environments>
    <!-- mybatis映射配置位置 -->
    <!-- 按模块映射不同的配置文件,让配置文件看起来更简洁 -->
    <mappers>
        <mapper resource="映射配置文件全路径"></mapper>
    </mappers>
</configuration>
  • springboot中的**application.yml**
yaml 复制代码
mybatis:
  # mapper配置文件
  mapper-locations: classpath:mapper/*.xml
  # resultType别名,没有这个配置resultType包名要写全,配置后只要写类名
  type-aliases-package: com.mashang.xiaomistore.domain
  configuration:
    #下划线自动转驼峰
    map-underscore-to-camel-case: true
  • 创建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.company.mapper.StudentMapper">
    <select id="queryAll" resultType="com.company.entity.Student">
        SELECT * FROM student
    </select>
</mapper>
  • 创建Mapper接口:
csharp 复制代码
public interface StudentMapper {
    List<Student> queryAll();
}

MyBatis日志配置

  • 引入SpringBoot中的log4j
xml 复制代码
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-log4j2 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
    <version>3.4.3</version>
</dependency>
  • 在SpringBoot中在**application.yml mybatis**配置项中进行配置
yaml 复制代码
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.log4j.Log4jImpl
  • 配置**log4j.properties**文件
ini 复制代码
### 设置###
log4j.rootLogger = debug,stdout,D,E

### 输出信息到控制抬 ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### 输出DEBUG 级别以上的日志到=D://logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = D://logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG 
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

### 输出ERROR 级别以上的日志到=D://logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =D://logs/error.log 
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n
  • 一个基本的mybatis的XML模板如下
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.example.mapper.UserMapper">
    <!-- CRUD 配置 -->
</mapper>

CURD实现

select查询

  • 使用 <select> 标签实现基本查询
sql 复制代码
<select id ="getUserById" resultType="com.company.domain.entity.User">
		SELECT * FORM user 
</select>

*

  • id:对应Mapper接口中的方法名,必须一致

    resultType:指定返回结果映射到哪个Java类

  • 传参 #{}${} 的区别

    #{} 的特点事先进行预编译:使用 #{} 的参数会被Mybatis当作JDBC中的 ? 占位符防止sql注入:由于会事先进行预编译,Mybatis能够防止Sql注入类型转换:会根据参数类型进行适当的类型转换

    ${} 的特点字符串拼接: &{} 直接将字符串进行替换,相当于在Sql中直接拼接传入的参数存在sql注入的风险:没有预编译,会引发sql注入问题

  • 多条件查询

sql 复制代码
<select id="getUserByNameAndAge" resultType="User">
    SELECT * FROM user 
    WHERE name = #{name} AND age = #{age}
</select>
  • 模糊查询
sql 复制代码
<select>
        SELECT *
        FROM user
        WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
  • 使用LIKE关键字和CONCAT()函数进行查询

insert插入

  • 使用 <insert> 标签实现基本插入操作
sql 复制代码
    <insert id="insertUser" parameterType="User">
        INSERT INTO user(name, age)
        VALUES (#{name}, #{age})
    </insert>
  • parameterType:表示入参类型

  • 实现回填自增主键

    使用**userGeneratedKeys keyProperty**实现

sql 复制代码
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
    INSERT INTO user (name, age) 
    VALUES (#{name}, #{age})
</insert>
  • userGeneratedKeys:表示是否启动自增

    keyProperty :表示将生成的主键赋值给哪个java对象的哪个属性如**user.id**

update更新

  • 使用 <update> 标签实现基本更新
bash 复制代码
	 <update id="updateUser" parameterType="User">
        UPDATE user
        SET name=#{name},
            age =#{age}
        WHERE id = #{id}
    </update>

delete删除

  • 使用 <delete> 标签基本查询
sql 复制代码
    <delete id="deleteUserById" parameterType="Integer">
        DELETE
        FROM user
        WHERE id = #{id}
    </delete>

传参方式

  • 多参数传参(使用@Param)

    当方法有多个参数时,使用 **@Param**注解明确参数名

sql 复制代码
<select id="getUserByNameAndAge" resultType="User">
    SELECT * FROM user 
    WHERE name = #{name} AND age = #{age}
</select>
  • Mapper接口
less 复制代码
    User getUserByNameAndAge(
            @Param("name") String name,
            @Param("age") Integer age);

对象参数

  • 当参数为一个Java对象时,MyBatis自动将对象属性映射到Sql语句中的占位符
sql 复制代码
<insert id="insertUser" parameterType="User">
    INSERT INTO user (name, age) 
    VALUES (#{name}, #{age})
</insert>
arduino 复制代码
void insertUser(User user);

Map参数

  • 通过Map传递多个参数或动态参数
sql 复制代码
<select id="getUserByMap" resultType="User">
    SELECT * FROM user 
    WHERE name = #{name} AND age = #{age}
</select>
  • Mapper接口
javascript 复制代码
User getUserByMap(Map<String, Object> params);

集合/数组参数

  • 适用于批量查询,比如WHERE id IN (...)
sql 复制代码
<select id="getUsersByIds" resultType="User">
    SELECT * FROM user 
    WHERE id IN
    <foreach collection="ids" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>
  • <foreach> 是动态sql中的知识点等下会系统讲解
  • Mapper接口
less 复制代码
List<User> getUsersByIds(@Param("ids") List<Integer> ids);

动态sql

与标签

  • <where> :生成WHERE子句,并自动判断去掉开头多余的**AND/OR**关键字,使sql更简洁
  • <if> :用于判断传参条件,根据条件决定是否拼接某段SQL语句,适用于传参条件不固定,只有在满足条件时接入某个子串
bash 复制代码
<select id="getUserByCondition" resultType="User">
    SELECT * FROM user
    <where>
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </where>
</select>
  • 当**name为非空,会添加 AND name LIKE CONCAT('%', #{name}, '%')** 当**age**为非空时会添加 AND age = #{age}
  • 结合标签使用,能自动处理首个AND,使得SQL语句正确
  • 其作用在于动态拼接SQL片段前添加或去除特点字符,比如前缀,后缀,以及多余的分隔符如 ,
  • 常用于INSERT和UPDATE语句,避免出现多余逗号

INSERT语句

ini 复制代码
<insert id="insertUserSelective" parameterType="User">
    INSERT INTO user
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="name != null">name,</if>
        <if test="age != null">age,</if>
        <if test="email != null">email,</if>
    </trim>
    VALUES
    <trim prefix="(" suffix=")" suffixOverrides=",">
        <if test="name != null">#{name},</if>
        <if test="age != null">#{age},</if>
        <if test="email != null">#{email},</if>
    </trim>
</insert>
  • 标签包裹字段列表和对应值部分
  • suffixOverrides="," 表示自动去除多余的逗号,确保sql语法正确

UPDATE语句

  • <set> 标签是 <trim> 的特性化
bash 复制代码
<update id="updateUserDynamic" parameterType="User">
    UPDATE user
    <set>
        <if test="name != null">name = #{name},</if>
        <if test="age != null">age = #{age},</if>
        <if test="email != null">email = #{email},</if>
    </set>
    WHERE id = #{id}
</update>
  • <set> 标签内部原理类似 <trim> ,会自动去除多余逗号
  • <foreach> 用于遍历集合,数组和Map,常用于批量操作或动态生成IN子句
  • 其主要属性collection:集合或数组名称(可用 @Param() 指定对应名称,默认为**list array**)item:循环时每个元素的别名open:循环生成sql片段的前缀separator:循环时的分隔符close:循环生成sql片段的后缀
bash 复制代码
<select id="getUsersByIds" resultType="User">
    SELECT * FROM user
    <where>
        <if test="ids != null">
            AND id IN
            <foreach collection="ids" item="id" open="(" separator="," close=")">
                #{id}
            </foreach>
        </if>
    </where>
</select>
  • 当ids不为null时,进入 <if test="ids != null"> 生成的sql片段为 SELECT * FROM AND WHERE id IN(#{id},#{id},...)
  • 其中标签遍历集合ids,用逗号进行分隔,并在开头添加 ( 括号,结尾添加 ) 括号
  • 最终标签会去除第一个AND,使sql合法**SELECT * FROM id WHERE IN(#{id},#{id},...)**

MyBatis的映射

基本映射

用于单一的字段对应

  • 假设有一个user表,其中有字段**id,name,age其在Java中有个简单的对应类User,其属性分别也是 id,name,age**那么在Mapper.xml进行select查询时
sql 复制代码
SELECT id, name, age FROM user WHERE id = #{id}

*

  • MyBatis会将查询的结果中每一列值自动赋值给User对象中相同的属性

    数据库列表的id→User对象的id

    数据库列表的name→User对象的name

    数据库列表的age→User对象的age

  • 这样可能就会出现一种情况,数据库列表的列名与对象的属性名不一致,通常使用开启驼峰转换来解决→在**application.yml**的mybatis配置中添加如下配置:

vbnet 复制代码
mybatis:
    map-underscore-to-camel-case: true

一对一映射

当查询中需要查询一个对象时

  • 现假设,数据库有两张表一个user(用户)表,另一个user_detail(用户详细信息)表,在Java中我们可以创建两个类User和UserDetail类
  • 然后再创建一个UserVo类,其中包含User的属性和一个UserDatail对象
vbnet 复制代码
public class User {
    private Integer id;
    private String name;
    private Integer age;
}

public class UserDetail {
    private Integer detailId;
    private String address;
    private String phone;
}

public class UserVo {
    private Integer id;
    private String name;
    private Integer age;
    private UserDetail userDetail;  // 一对一关系:一个用户对应一份详细信息 
}

XML配置如下:

xml 复制代码
<resultMap id="userVoMap" type="com.example.UserVo">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <result property="age" column="age"/>
    <!-- 一对一映射 -->
    <association property="userDetail" javaType="com.example.UserDetail">
        <id property="detailId" column="detail_id"/>
        <result property="address" column="address"/>
        <result property="phone" column="phone"/>
    </association>
</resultMap>

<select id="getUserVoById" resultMap="userVoMap" parameterType="int">
    SELECT u.id, u.name, u.age, ud.detail_id, ud.address, ud.phone
    FROM user u
    LEFT JOIN user_detail ud ON u.id = ud.user_id
    WHERE u.id = #{id}
</select>
  • <resultMap> 标签用于定义一组映射规则,将查询的结果转换为一个指定类型的Java对象属性id:为该映射指定一个唯一标识,供其在XML中引用使用,如 <resultMap id="userResultMap" type="com.example.User"> type:指定映射结果对应的Java类型(对象的全路径)
  • <result> 标签用于将数据库列映射到Java对象的属性,在 <resultMap> 中使用属性property:Java对象中的属性名称,如 <result property="userName" column="user_name"/> 其表示将查询到的user_name列的值赋值给userName属性cloumn:数据库查询结果中的列名,如**column="user_name"** 表示sql查询列名为user_name的值
  • <id> 标签 <id> 类似于 <result> 主要用于映射主键字段属性property:与 <result> 相同,映射到Java对象的主键属性 column:对应数据库中的主键列名
  • <association> 标签表示一个一对一关连当查询到结果时,MyBatis会将用户的基本字段 {id,name,age} 直接映射到UserVo中,同时将详细信息 {detail_id,address,phone} 封装为一个UserDetail对象,并赋值到UserVo的**userDetail**对象中

一对多映射

提供用于有列表对象的查询

  • 现假设一个老师(Teacher)类和一个学生(student)类,一个老师可以对应多个学生,在Java中我们可以设计Teacher类, 使用List属性来存放老师的所有学生
vbnet 复制代码
public class Teacher {
    private Integer id;
    private String teacherName;
    private Integer age;
    private List<Student> students; // 一对多关系:一个老师对应多个学生
}

public class Student {
    private Integer id;
    private String name;
    private Integer age;
}

XML配置如下:

xml 复制代码
<resultMap id="teacherMap" type="com.example.Teacher">
    <id property="id" column="teacher_id"/>
    <result property="teacherName" column="teacher_name"/>
    <result property="age" column="teacher_age"/>
    <!-- 一对多映射 -->
    <collection property="students" ofType="com.example.Student">
        <id property="id" column="student_id"/>
        <result property="name" column="student_name"/>
        <result property="age" column="student_age"/>
    </collection>
</resultMap>

<select id="getTeacherWithStudents" resultMap="teacherMap" parameterType="int">
    SELECT t.id as teacher_id, t.teacher_name, t.age as teacher_age,
           s.id as student_id, s.name as student_name, s.age as student_age
    FROM teacher t
    LEFT JOIN student s ON t.id = s.teacher_id
    WHERE t.id = #{id}
</select>
  • <collection> 标签:用于表示一对多关系,把查询结果中的学生记录封装成一个列表,并赋值到Teacher对象中的**student**属性

文章转载自: ihav2carryon

原文链接: www.cnblogs.com/ihave2carry...

体验地址: www.jnpfsoft.com/?from=001YH

相关推荐
周小闯29 分钟前
Easyliev在线视频分享平台项目总结——SpringBoot、Mybatis、Redis、ElasticSearch、FFmpeg
spring boot·redis·mybatis
我自闭了10 小时前
PageHelper和Mybatis-Plus分页
后端·mybatis
半城抹茶1 天前
关于更新字段为空值——MybatisPlus框架
java·mybatis
雾喔1 天前
Java的缓存
java·缓存·mybatis
等什么君!1 天前
Mybatis缓存机制(一级缓存和二级缓存)
java·缓存·mybatis
Warren981 天前
MySQL DDL数据定义语句
数据库·spring boot·笔记·mysql·oracle·tomcat·mybatis
好奇的菜鸟2 天前
在Spring Boot + MyBatis中优雅处理多表数据清洗:基于XML的配置化方案
xml·spring boot·mybatis
岁岁岁平安2 天前
SpringMVC学习(controller层加载控制与(业务、功能)bean加载控制、Web容器初始化配置类)(3)
java·学习·spring·mybatis·springmvc
2401_853275732 天前
能简述一下动态 SQL 的执行原理吗
java·sql·mybatis
neeef_se2 天前
IDEA搭建SpringBoot,MyBatis,Mysql工程项目
spring boot·intellij-idea·mybatis