MyBatis与其使用方法讲解
ORM
在讲解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的基本使用
环境准备
- 引入依赖包:
<!--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 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&serverTimezone=Asia/Shanghai"/>
<property name="username" value="帐号"/>
<property name="password" value="密码"/>
</dataSource>
</environment>
</environments>
<!-- mybatis映射配置位置 -->
<!-- 按模块映射不同的配置文件,让配置文件看起来更简洁 -->
<mappers>
<mapper resource="映射配置文件全路径"></mapper>
</mappers>
</configuration>
- springboot中的
application.yml
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 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接口:
public interface StudentMapper {
List<Student> queryAll();
}

MyBatis日志配置
- 引入SpringBoot中的log4j
<!-- 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配置项中进行配置
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.log4j.Log4jImpl
- 配置
log4j.properties文件
### 设置###
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 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>标签实现基本查询<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注入问题
- 字符串拼接:
多条件查询
<select id="getUserByNameAndAge" resultType="User">
SELECT * FROM user
WHERE name = #{name} AND age = #{age}
</select>模糊查询
<select>
SELECT *
FROM user
WHERE name LIKE CONCAT('%', #{name}, '%')
</select>
- 使用LIKE关键字和CONCAT()函数进行查询
insert插入
使用
<insert>标签实现基本插入操作<insert id="insertUser" parameterType="User">
INSERT INTO user(name, age)
VALUES (#{name}, #{age})
</insert>
parameterType:表示入参类型
实现回填自增主键
- 使用
userGeneratedKeys和keyProperty实现
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
INSERT INTO user (name, age)
VALUES (#{name}, #{age})
</insert>
userGeneratedKeys:表示是否启动自增keyProperty:表示将生成的主键赋值给哪个java对象的哪个属性如user.id
- 使用
update更新
使用
<update>标签实现基本更新<update id="updateUser" parameterType="User">
UPDATE user
SET name=#{name},
age =#{age}
WHERE id = #{id}
</update>
delete删除
使用
<delete>标签基本查询<delete id="deleteUserById" parameterType="Integer">
DELETE
FROM user
WHERE id = #{id}
</delete>
传参方式
多参数传参(使用@Param)
- 当方法有多个参数时,使用
@Param注解明确参数名
<select id="getUserByNameAndAge" resultType="User">
SELECT * FROM user
WHERE name = #{name} AND age = #{age}
</select>
- Mapper接口
User getUserByNameAndAge(
@Param("name") String name,
@Param("age") Integer age);
- 当方法有多个参数时,使用
对象参数
- 当参数为一个Java对象时,MyBatis自动将对象属性映射到Sql语句中的占位符
<insert id="insertUser" parameterType="User">
INSERT INTO user (name, age)
VALUES (#{name}, #{age})
</insert>#{name}对应user.name,#{age}对应user.age- Mapper接口
void insertUser(User user);
Map参数
- 通过Map传递多个参数或动态参数
<select id="getUserByMap" resultType="User">
SELECT * FROM user
WHERE name = #{name} AND age = #{age}
</select>- Mapper接口
User getUserByMap(Map<String, Object> params);
集合/数组参数
- 适用于批量查询,比如WHERE id IN (…)
<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接口
List<User> getUsersByIds(@Param("ids") List<Integer> ids);
动态sql
与标签
<where>:生成WHERE子句,并自动判断去掉开头多余的AND/OR关键字,使sql更简洁<if>:用于判断传参条件,根据条件决定是否拼接某段SQL语句,适用于传参条件不固定,只有在满足条件时接入某个子串
<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语句
<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>的特性化
<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片段的后缀
- collection:集合或数组名称(可用
<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查询时SELECT id, name, age FROM user WHERE id = #{id}
MyBatis会将查询的结果中每一列值自动赋值给User对象中相同的属性
- 数据库列表的id→User对象的id
- 数据库列表的name→User对象的name
- 数据库列表的age→User对象的age
这样可能就会出现一种情况,数据库列表的列名与对象的属性名不一致,通常使用开启驼峰转换来解决→在
application.yml的mybatis配置中添加如下配置:mybatis:
map-underscore-to-camel-case: true
一对一映射
当查询中需要查询一个对象时
- 现假设,数据库有两张表一个user(用户)表,另一个user_detail(用户详细信息)表,在Java中我们可以创建两个类User和UserDetail类
- 然后再创建一个UserVo类,其中包含User的属性和一个UserDatail对象
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配置如下:
<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类型(对象的全路径)
- id:为该映射指定一个唯一标识,供其在XML中引用使用,如
<result>标签- 用于将数据库列映射到Java对象的属性,在
<resultMap>中使用 - 属性
- property:Java对象中的属性名称,如
<result property="userName" column="user_name"/>其表示将查询到的user_name列的值赋值给userName属性 - cloumn:数据库查询结果中的列名,如
column="user_name”表示sql查询列名为user_name的值
- property:Java对象中的属性名称,如
- 用于将数据库列映射到Java对象的属性,在
<id>标签<id>类似于<result>主要用于映射主键字段- 属性
- property:与
<result>相同,映射到Java对象的主键属性 - column:对应数据库中的主键列名
- property:与
<association>标签- 表示一个一对一关连
- 当查询到结果时,MyBatis会将用户的基本字段
{id,name,age}直接映射到UserVo中,同时将详细信息{detail_id,address,phone}封装为一个UserDetail对象,并赋值到UserVo的userDetail对象中
一对多映射
提供用于有列表对象的查询
现假设一个老师(Teacher)类和一个学生(student)类,一个老师可以对应多个学生,在Java中我们可以设计Teacher类, 使用List属性来存放老师的所有学生
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配置如下:
<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属性
MyBatis与其使用方法讲解的更多相关文章
- MyBatis dao层 方法传参
MyBatis dao层 方法传参有三种方法. 1. 以下标的方法获取参数. <update id="insertSuccessKilled"> INSER ...
- 【转】Nginx服务器的反向代理proxy_pass配置方法讲解
[转]Nginx服务器的反向代理proxy_pass配置方法讲解 转自:http://www.jb51.net/article/78746.htm 就普通的反向代理来讲Nginx的配置还是比较简单的, ...
- 使用mybatis开发dao方法
使用mybatis开发dao的时候, 主要涉及到SqlSessionFactoryBuilder.SqlSessionFactory.SqlSession 这三个类 现在将这三个类的使用方法简单的说下 ...
- AJAX方法讲解
Ajax的方法讲解 Ajax 异步请求,有点: 调高用户的体验度, 降低网络传输量 $.load() //异步加载页面 $.post() Post 异步请求 $.post("url请求地址 ...
- iOS7中UIView的animateKeyframesWithDuration方法讲解
iOS7中UIView的animateKeyframesWithDuration方法讲解 在iOS7中,给UIView添加了一个方法用来直接使用关键帧动画而不用借助CoreAnimation来实现,那 ...
- NSArray排序方法讲解
NSArray排序方法讲解 给数组排序有着多种方式 最麻烦的是sortedArrayUsingSelector:,其次是sortedArrayUsingDescriptors:,最容易使用的就是sor ...
- 007-对象—— static静态方法属性内存构成及使用方法讲解
<?php /* 7 对象 static静态方法属性内存构成及使用方法讲解 */ /*class a{ public $uname=11; static public function _a() ...
- Python单元测试框架unittest使用方法讲解
这篇文章主要介绍了Python单元测试框架unittest使用方法讲解,本文讲解了unittest概述.命令行接口.测试案例自动搜索.创建测试代码.构建测试套件方法等内容,需要的朋友可以参考下 概 ...
- 【Java EE 学习 79 上】【mybatis 基本使用方法】
一.简介 mybatis类似于hibernate,都是简化对数据库操作的框架,但是和hibernate不同的是,mybatis更加灵活,整体来说框架更小,这体现在它需要我们手写SQL语句,而hiber ...
- jQuery&HTML&CSS3实现垂直手风琴折叠菜单方法讲解
在网页制作中我们常常需要折叠式的菜单,在折叠菜单中,手风琴特效的菜单是非常受欢迎,下面就讲解使用jQuery+HTML+CSS3实现垂直手风琴折叠菜单的方法. jQuery实现垂直手风琴折叠菜单示例代 ...
随机推荐
- Unity 3D简单使用C#脚本,脚本的生命周期
Unity 3D简单使用 新建项目->层级里右键->创建空对象改名Test 项目里右键创建C#脚本Test 双击脚本Test(所有脚本都会继承MonoBehaviour类),在Start( ...
- Qt编写物联网管理平台46-云端数据同步
一.前言 在上一篇文章说的采集数据转发的基础上,针对方案一还做了云端数据同步功能,满足各式各样的用户需求.云端数据库同步,相当于把本地采集到的数据实时存储到云端,至于这些记录到了云端后什么用途,客户端 ...
- Qt音视频开发19-海康sdk录像存储
一.前言 关于调用海康sdk来进行录像存储,整体的框架架构处理流程沿袭了之前vlc内核.ffmpeg内核.mpv内核的做法,定时存储这块,开个定时器判断,到了时间则先关闭原来的录像存储,然后在开始一个 ...
- 鸿蒙OS高级技巧:打造个性化动态Swiper效果
前言 在鸿蒙OS的广阔天地中,开发者们有机会创造出令人惊叹的用户体验.最近,我着手设计一款具有独特滑动效果的Swiper组件,它在滑动时能够迅速进入视野,同时巧妙地将旧的cell隐藏到视线之外.本文将 ...
- 不为人知的网络编程(十四):拔掉网线再插上,TCP连接还在吗?一文即懂!
本文由作者小林coding分享,来自公号"小林coding",有修订和改动. 1.引言 说到TCP协议,对于从事即时通讯/IM这方面应用的开发者们来说,再熟悉不过了.随着对TCP理 ...
- JMeter:强大的性能测试工具
揭秘 JMeter:性能测试的得力助手 宝子们,今天咱来唠唠在软件测试这旮旯里超厉害的 JMeter!这玩意儿就像是个超级侦探,能帮咱摸清楚软件系统在人多手杂的时候到底表现咋样. 一.JMeter 是 ...
- 树莓派Zero OLED屏幕转接板
买了个树莓派Zero,emmm,拿到手后感觉很精巧,但是总是感觉少了什么.于是... 瞎吹一波:不得不说嘉立创公司确实给力,一条龙服务而且价格太便宜了. 焊接组装上机测试,OK! 其实这个过程中坑也踩 ...
- MS Webview2 拦截 interact/intercept
https://docs.microsoft.com/en-us/microsoft-edge/webview2/how-to/webresourcerequested?tabs=dotnet 自定义 ...
- 浅说 c++20 coroutine
浅说cppcoro 上一篇<浅说c/c++ coroutine>介绍了stackful协程,举了win32 Fiber跟tencent/libco为例. 本篇https://www.cnb ...
- uniapp横向滚动
scroll-x="true" 出现横向滚动 scroll-with-animation="true" 横向滚动有动画 <scroll-view clas ...