目录
介绍
MyBatis 是一款优秀的ORM 持久层框架 , 具有较高的SQL灵活性 , 支持高级映射 .
ORM : Object Relation Mapping 对象关系映射 , 指的就是在Java 对象 和 数据库 的关系模型之间建立起一种对应关系 , 例如 : 一个article类 对应数据库中的一张 article 表 , 表中的字段和 对象中的属性一一对应 .
简单来说 MyBatis 是更简单完成程序和数据库交互的工具 , 也就是更简单的操作和读取数据库工具 .
配置 MyBatis 开发环境
添加依赖 :
配置连接信息
# 配置数据库的连接字符串
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8
username: root
password: "111111"
driver-class-name: com.mysql.cj.jdbc.Driver
# 设置 Mybatis 的 xml 保存路径
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
* Mapper 层的代码实现
@Mapper
public interface StaffMapper {
Staff getStaffById(@Param("id") Integer id);
}
<?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.demo.mapper.StaffMapper">
<select id="getStaffById" resultType="com.example.demo.entity.Staff">
select * from staff where id=${id}
</select>
</mapper>
接口中的方法通过 xml 配置文件来实现 : 使用了 select 标签来获取职员信息 , id 存放的是接口方法名 , resultType 是返回的参数类型 , 通过 $ 来获取接口方法中的参数 (@Param()注解的参数).
注 : 如果不适用 @Param 注解 , 直接使用方法的参数名获取,也可以 .
返回一组数据 , 使用 List 来接收 :
@Mapper
public interface StaffMapper {
/**
* 查询全部
* @return
*/
List<Staff> getAll();
}
<select id="getAll" resultType="com.example.demo.entity.Staff">
select * from staff
</select>
注意 : xml 中 返回类型是最小单元 , 也就是 Staff , 并不是 List .
添加操作
在接口中定义方法 :
int add(Staff staff);
在 xml 文件中进行方法的具体实现 :
<insert id="add">
insert into staff(name,age) values(#{name},#{id})
</insert>
注意 : 在使用 insert 标签时 , 默认返回的类型就是 受影响行数的个数 .
在传值的时候 , 可以传递一个对象 .
xml 中在获取值的时候 , 直接获取对象中的属性 .
修改上述代码 , 让其返回 id .
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into staff(id,name) values(#{id},#{name})
</insert>
返回类型还是受影响的行数 , 另外它还会将 id 自动设置给 staff 对象 .
补充 : 使用增(insert) 删(delete) 改(update) , 在 xml 文件中是不用设置返回值的, 默认返回的都是受影响的行数 .
打印 MyBatis 生成的 SQL
mybatis:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 配置打印 MyBatis 执行的 SQL
logging:
level:
com:
example:
demo: debug
参数占位符
#{} : 预编译处理. 在程序编译时 会将 SQL 中的 #{} 替换为 ? , 然后使用 PreparedStatement 的set 方法来赋值 . (会将 ? 这个位置上的值当做是一个字符串), 不会有SQL注入的风险 .
${} : 字符直接替换 . 对于 $ 来说它直接就进行了替换 . $ 常用于排序, 因为 asc desc 这两个都是 sql 语句的关键词. 如果使用#得到的结果就是 "asc" "desc" , 就会导致变成了字符串形式 . 而$ 直接进行了替换 , 表达的就是关键词本身的意思 . 会存在 SQL 注入的问题.
如果是 # 那么表示占位符 .
而如果是 $ , 会直接进行替换 .
Like 查询
方法 : 使用 concat 关键词 进行拼接 .
<select id="getStaffByName" resultType="com.example.demo.entity.Staff"> select * from staff where name like concat('%',#{name},'%') </select>
使用 $ 会存在SQL注入的风险 .
resultMap
当对象中的属性和数据中的字段名不一致时 , 就不能成功的进行传值和赋值.
可以使用 resultMap : 返回字典映射
<!-- 声明 resultMap-->
<resultMap id="baseMap" type="com.example.demo.entity.Staff">
<id column="id" property="id"></id>
<result column="name" property="staffName"></result>
<result column="age" property="age"></result>
</resultMap>
使用 :
<!-- 声明 resultMap-->
<resultMap id="baseMap" type="com.example.demo.entity.Staff">
<id column="id" property="id"></id>
<result column="name" property="staffName"></result>
<result column="age" property="age"></result>
</resultMap>
<select id="getStaffById" resultMap="baseMap">
select * from staff where id=${id}
</select>
另外 , 当字段和属性不一致时 , 也可以使用 MySQL中起别名的方式 . as
<select id="getStaffById" resultType="com.example.demo.entity.Staff">
select id,name as staffName,age from staff where id=${id}
</select>
动态SQL
在日常中 , 通常去注册一个账号时 , 会有必填项和非必填项 , 前端传输到后端中 , 我们不确定那些字段有值那些字段没有值 , 因此 使用动态SQL就能很好的解决这个问题 .
if 标签
<insert id="add" useGeneratedKeys="true" keyProperty="id">
insert into staff(id,name
<if test="age!=null">
,age
</if>
)
values(#{id},#{name}
<if test="age!=null">
,#{age}
</if>
)
</insert>
trim 标签
<trim> 标签中的属性 :
prefix : 在语句块的最前面加上 prefix 的值
suffix : 在语句块的最后面加上 suffix 的值
prefixOverrides : 如果语句块的最前面的值是 prefixOverrides 的值就删掉 .
suffixOverrides : 如果语句块的最后面的值是 suffixOverrides 的值就删掉 .
<insert id="addUser">
insert into staff
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id!=null">
id,
</if>
<if test="name!=null">
name,
</if>
<if test="age!=null">
age,
</if>
</trim>
values
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id!=null">
#{id},
</if>
<if test="name!=null">
#{staffName},
</if>
<if test="age!=null">
#{age},
</if>
</trim>
</insert>
注 : 当 <trim> 中没有任何值时 , 那么prefix 的值 和 suffix 的值都不会被添加 .
where 标签
where 标签通常要配合 if 标签 一起使用 .
where 标签会删除最前面的 and / or 关键字 (但是不会删除最后面的 and / or 关键字)
如果 where 标签中没有内容 , 那么它也不会生成 where sql 关键字 .
<select id="getId" resultType="com.example.demo.entity.Staff">
select * from staff
<where>
<if test="age!=null">
#{age}>18
</if>
<if test="name!=null">
or name=#{name}
</if>
</where>
</select>
set 标签
set 标签 通常要配合 if 标签一起使用 , set 标签会自动删除最后一个逗号 .
<update id="setIdStaff">
update staff
<set>
<if test="name!=null">
name=#{name},
</if>
<if test="age!=null">
age=#{age},
</if>
</set>
where id=#{id}
</update>
foreach 标签
<foreach> 标签常用属性 :
collection : 绑定方法参数中的集合 , 例如 : List , Set , Map 或数组对象
itam : 遍历时的,每一个对象
open : 语句块开头的字符串
close : 语句块结束的字符串
separator : 每次遍历之间间隔的字符串 .
// 接口 方法
int delById(List<Integer> ids);
// xml文件中的 具体实现
<delete id="delById">
delete from staff where id in
<foreach collection="ids" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>
End.....