准备操作
- 创建员工表emp
- 创建新springboot工程 , 选择引入依赖(mybatis , mysql驱动 , lombok)
- application.properties中引入数据库连接信息
- 创建对应实体类Emp
- 准备接口mapper
1.删除
Mapper/EmpUser
package com.kitten.mybatis_usage.mapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EmpMapper {
// 根据Id删除数据
@Delete("delete from emp where id = #{id}")
public void deleteById(Integer id);
}
需要注意 :
- 如何传参 , 通过#{} , 这种是通过预编译的方式 , 能提高效率 , 也能防止sql注入(通过占位符而不是直接传递参数)
- 配置日志输出项 `application.properties`
#配置mybatis日志输出项 mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl - ${} , 这种是通过拼接的方式 将参数拼接到 SQL 语句中 , 存在SQL注入问题 , 一般多用于对表名或者列表进行动态设置时 使用
2.新增
可以自己尝试写一下 , 并不难
新建pojo/emp 实体类
package com.kitten.mybatis_usage.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer id;
private String username;
private String password;
private String name;
private short gender;
private String image;
private short job;
private LocalDate entrydate;
private Integer deptId;
// localdataetime 既包含年月日 又包含 十分秒
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
mapper/Empmapper
package com.kitten.mybatis_usage.mapper;
import com.kitten.mybatis_usage.pojo.Emp;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EmpMapper {
// 根据Id删除数据
@Delete("delete from emp where id = #{id}")
public void deleteById(Integer id);
// 新增数据
@Insert("insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")
public void insertEmp(Emp emp);
}
test单元测试类
...
@Test
public void testAdd(){
Emp emp = new Emp();
emp.setUsername("Tony");
emp.setName("kitten");
emp.setGender((short)1);
emp.setImage("1.jpg");
emp.setJob((short)1);
emp.setEntrydate(LocalDate.of(2000,1,1));
emp.setDeptId(1);
emp.setCreateTime(LocalDateTime.now());
emp.setUpdateTime(LocalDateTime.now());
empMapper.insertEmp(emp);
}
2.1新增-主键返回
数据添加成功后,需要获取插入数据的主键
@Options(keyProperty="id",useGeneratedKeys=true)
@Insert(...)
...
其中useGeneratedKeys=true 表明要获取到返回的主键值
3.更新
mapper/Empmapper
// 更新数据
@Update("update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},"+
"job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id = #{id}")
public void updateById(Emp emp);
test
...
@Test
public void testUpdate(){
Emp emp = new Emp();
emp.setId(18);
emp.setUsername("TheKitten");
emp.setName("kitten");
emp.setGender((short)1);
emp.setImage("2.jpg");
emp.setJob((short)4);
emp.setEntrydate(LocalDate.of(2000,1,1));
emp.setDeptId(1);
emp.setUpdateTime(LocalDateTime.now());
// 执行更新员工操作
empMapper.updateById(emp);
}
一般我们实现更新时 , 都要进行回显展示
4.查询
首先要查询
mapper/Empmapper
@Select("select * from emp where id = #{id}")
public emp getById(Integer id);
test
@Test
public void testGetById(){
Emp emp = empMapper.getById(18);
sout-> emp;
}
这里输出的时候 , 由于 数据库中设置的字段名 有 dept_id , create_time 和 update_time , 但是我们定义的类的 属性名称分别是 deptId , createTime 和 updateTime, 所以 打印出来的结果为 null
对于前面几个属性 , id , username …… 这些 实体类属性名 和 数据库表查询返回的字段名 一致,mybatis会自动进行封装
解决方案:
// 解决方案一 : 起别名
@Select("select id, username, password, name, gender, image, job, entrydate,"+
" dept_id deptId, create_time createTime, update_time updateTime from emp where id = #{id}")
public Emp getById(Integer id);
// 解决方案二 : @results 手动映射封装
@Results({
@Result(column = "dept_id", property = "deptId"),
@Result(column = "create_time", property = "createTime"),
@Result(column = "update_time", property = "updateTime")
})
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);
解决方案三 : 开启mybatis驼峰命名自动转换(常用)
application.properties
mybatis.configuration.map-underscore-to-camel-case=true
4.1条件查询
根据前端输入的员工信息 , 员工性别 , 入职时间 搜索满足条件的员工信息
mapper/EmpMapper
// 条件查询 注意like后面接的 pattern , 不用#{} 而是用 ${}
@Select("select * from emp where name like '%${name}%' and gender= #{gender} and "+
"entrydate between #{begin} and #{end} order by update_time desc")
public List list(String name, Short gender, LocalDate begin , LocalDate end);
test
//条件查询
...
@Test
public void testList(){
List list = empMapper.list("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
System.out.println(list);
}
注意 这里的like 运算符后面 还是跟了 ${} , 这样就会导致下面几个问题 :
- 性能低 , 通过拼接字符串的方式 , 不会预编译
- 不安全 , 存在SQL注入问题
如何解决? 通过mysql 提供的 concat() 拼接函数
@Select("select * from emp where name like concat('%',#{name},'%') and gender= #{gender} and "+
"entrydate between #{begin} and #{end} order by update_time desc")
public List list(String name, Short gender, LocalDate begin , LocalDate end);
在springboot1.x版本中 , 需要在参数前 加上 @param 这个注解
XML映射文件
- 映射文件的名称与 Mapper 接口 名称一致 , 并且将XML文件 和Mapper几口放置在同包下
- XML的namespace 属性为Mapper接口全限定名一致
- XML映射文件中sql语句的id 和 Mapper 接口中的方法名一致,并与返回类型一致
例: java/com.kitten 下放了一个 mapper层 , 里面有一个EmpMapper接口 , 那么我要在resources 文件夹下建一个 com.kitten 包 , 里面放EmpMapper.XML文件
对于上面的 list方法 , 我们可以把 这一整段拆分成两部分 :
resources/com/kitten/mapper/EmpMapper.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.kitten.mapper.EmpMapper">
<!-- id 方法名 resultType 结果的单个类型 ArrayList里放的是emp , 那么类型就是emp-->
<select id="list" resultType="com.kitten.pojo.Emp">
select * from emp where name like concat('%',#{name},'%') and gender= #{gender} and
entrydate between #{begin} and #{end} order by update_time desc
</select>
</mapper>
mapper/EmpMapper
@Mapper
public List list(String name, Short gender, LocalDate begin , LocalDate end);
在mybatis官方文章中 , 说明了我们可以在什么时候使用XML映射 , 当我们写一些逻辑很简单的SQL语句时 , 可以直接在方法上面写注解 , 但是在写一些相对复杂的SQL语句时 , 最好还是用XML映射
动态SQL
随着外部条件变化 而变化的语句叫动态sql
1.动态select
主要要明白的有<if> , <where>
将resources/com/kitten/mapper/EmpMapper.xml中的 <mapper>标签中的select语句改一下, 将语句改为 :
<select id="list" resultType="com.kitten.pojo.Emp">
select *
from mybatis.emp
<where>
<if test="name != null">
name like concat('%', #{name}, '%')
</if>
<if test="gender != null">
gender = #{gender}
</if>
<if test="begin != null and end != null">
entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc;
</select>
<if>标签能进行判断从而来拼接sql , 如果我们第一个参数是空,后面参数不为空时 , 拼接出的select语句中就有 where and ... ; 这样的话就会报SQLSyntaxError错误 , 所以我们可以使用<where>标签 , 它能动态拼接语句里的 and , or 运算符 , 而且 <if> 中的条件都不成立时 , 它会自动省略 where 子句
2.动态update
主要要明白的有: <set>
java/.../mapper/EmpMapper
...
// 动态更新
public void updateById(Emp emp);
resources/.../mapper/EmpMapper.xml
<update id="updateById">
# 动态更新员工操作
update mybatis.emp
<set>
<if test="username != null">username = #{username},</if>
<if test="name != null">name = #{name},</if>
<if test="gender != null">gender = #{gender},</if>
<if test="image != null">image = #{image},</if>
<if test="job != 0">job = #{job},</if>
<if test="entrydate != null">entrydate = #{entrydate},</if>
<if test="deptId != null">dept_id = #{deptId},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</set>
where id = #{id}
</update>
test
@Test
public void testUpdate(){
Emp emp = new Emp();
emp.setId(18);
emp.setUsername("Thekitten");
emp.setName("kitten10");
emp.setGender((short) 1);
emp.setImage("3.png");
emp.setUpdateTime(LocalDateTime.now());
empMapper.updateById(emp);
}
<set>标签是用来对<if> 中的 , 进行动态删除 , 和<where>类似
3.动态delete
主要是<foreach> 标签
resources/.../mapper/EmpMapper.xml
<delete id="deleteByIds">
# delete from mybatis.emp where id in (16,17,18)
delete from mybatis.emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>
java/.../mapper/EmpMapper
// 动态删除
public void deleteByIds(List ids);
test
...
// delete 遍历集合
@Test
public void testDelete(){
List ids = Arrays.asList(13, 14, 15);
empMapper.deleteByIds(ids);
}
4.重复语句
我们想再写一个select语句时 :
<select id="list_repeat" resultType="com.kitten.pojo.Emp">
select * from mybatis.emp
where id = #{id}
</select>
// 重复sql语句
public Emp list_repeat(Integer id);
可以发现这个sql 语句中的 select * from emp 与我们之前写的第一个select中的相似,这些想同的地方我们可以抽离除来,简化代码 :
resources/.../mapper/EmpMapper.xml
<mapper>
<sql id="commonSelect">
select *
from mybatis.emp
</sql>
...
<select id="list_repeat" resultType="com.kitten.pojo.Emp">
<include id="commonSelect" />
where id = #{id}
</select>
</mapper>
test里自行写测试方法
总结
mybatis的基本用法到这里就基本结束了 , 下面来整理一下做demo的整个流程 :
- 创建springBoot工程 : 勾选maven , mybatis framework 框架和 mysql 驱动 (之后还会勾选web)
- 连接数据库 : 配置
resources/application.properties下连接数据库信息(四个:驱动类名,数据库url,username和password) - 配置开发工具:
- maven下装lombok,自动为实体类添加getter/setter,全/无参构造
application.properties下配置mybatis日志输出项和自动转换驼峰命名
- 创建工程文件:
pojo/数据库实体类对应数据库中表中信息java/.../mapper/实体类Mapper接口定义操作数据库方法名以及参数resources/.../mapper/实体类Mapper.xml文件名称要和接口文件名称一致,xml文件中配置namespace
- 写sql语句 : xml文件一般是用来写复杂sql语句的,对于简单sql语句,我们直接写在test中就行 , 写动态sql语句时 , 注意各个标签的使用方式
搞明白流程后,我们回到springBoot文档中做一个综合案例

Comments NOTHING