Spring框架下Mybaits的使用
- 准备数据库
- 配置application.properties
- pom.xml添加lombok依赖
- 创建Emp实体类
- 准备Mapper接口:EmpMapper
- 预编译SQL
- 根据id查询数据
- Mapper接口方法
- 配置application.properties开启自动结果映射
- 单元测试
- 条件模糊查询
- Mapper接口方法
- 单元测试
- 根据主键删除数据
- Mapper接口方法
- 单元测试
- 添加数据
- Mapper接口方法
- 单元测试
- 主键返回
- Mapper接口方法
- 单元测试
- 根据员工id修改数据
- Mapper接口方法
- 单元测试
- XML配置文件规范
- XML配置步骤
- 第一步:创建xml文件
- 第二步:在EmpMapper接口中添加抽象方法
- 第三步:编写XML映射文件
- 第四步:测试
- MybatisX的使用
- MybatisX插件安装
- MybatisX使用
- 总结
准备数据库
-- 部门管理
create table dept
(id int unsigned primary key auto_increment comment '主键ID',name varchar(10) not null unique comment '部门名称',create_time datetime not null comment '创建时间',update_time datetime not null comment '修改时间'
) comment '部门表';
-- 部门表测试数据
insert into dept (id, name, create_time, update_time)
values (1, '学工部', now(), now()),(2, '教研部', now(), now()),(3, '咨询部', now(), now()),(4, '就业部', now(), now()),(5, '人事部', now(), now());-- 员工管理
create table emp
(id int unsigned primary key auto_increment comment 'ID',username varchar(20) not null unique comment '用户名',password varchar(32) default '123456' comment '密码',name varchar(10) not null comment '姓名',gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',image varchar(300) comment '图像',job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师',entrydate date comment '入职时间',dept_id int unsigned comment '部门ID',create_time datetime not null comment '创建时间',update_time datetime not null comment '修改时间'
) comment '员工表';
-- 员工表测试数据
INSERT INTO emp (id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time)
VALUES
(1, 'jinyong', '123456', '金庸', 1, '1.jpg', 4, '2000-01-01', 2, now(), now()),
(2, 'zhangwuji', '123456', '张无忌', 1, '2.jpg', 2, '2015-01-01', 2, now(), now()),
(3, 'yangxiao', '123456', '杨逍', 1, '3.jpg', 2, '2008-05-01', 2, now(), now()),
(4, 'weiyixiao', '123456', '韦一笑', 1, '4.jpg', 2, '2007-01-01', 2, now(), now()),
(5, 'changyuchun', '123456', '常遇春', 1, '5.jpg', 2, '2012-12-05', 2, now(), now()),
(6, 'xiaozhao', '123456', '小昭', 2, '6.jpg', 3, '2013-09-05', 1, now(), now()),
(7, 'jixiaofu', '123456', '纪晓芙', 2, '7.jpg', 1, '2005-08-01', 1, now(), now()),
(8, 'zhouzhiruo', '123456', '周芷若', 2, '8.jpg', 1, '2014-11-09', 1, now(), now()),
(9, 'dingminjun', '123456', '丁敏君', 2, '9.jpg', 1, '2011-03-11', 1, now(), now()),
(10, 'zhaomin', '123456', '赵敏', 2, '10.jpg', 1, '2013-09-05', 1, now(), now()),
(11, 'luzhangke', '123456', '鹿杖客', 1, '11.jpg', 5, '2007-02-01', 3, now(), now()),
(12, 'hebiweng', '123456', '鹤笔翁', 1, '12.jpg', 5, '2008-08-18', 3, now(), now()),
(13, 'fangdongbai', '123456', '方东白', 1, '13.jpg', 5, '2012-11-01', 3, now(), now()),
(14, 'zhangsanfeng', '123456', '张三丰', 1, '14.jpg', 2, '2002-08-01', 2, now(), now()),
(15, 'yulianzhou', '123456', '俞莲舟', 1, '15.jpg', 2, '2011-05-01', 2, now(), now()),
(16, 'songyuanqiao', '123456', '宋远桥', 1, '16.jpg', 2, '2010-01-01', 2, now(), now()),
(17, 'chenyouliang', '123456', '陈友谅', 1, '17.jpg', NULL, '2015-03-21', NULL, now(), now());
配置application.properties
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/数据库名
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=密码
#指定mybatis输出日志的位置, 输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 自动结果映射
mybatis.configuration.map-underscore-to-camel-case=true
pom.xml添加lombok依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
创建Emp实体类
//使用注解方式生成get、set、toString、构造器等
@Data //getter方法、setter方法、toString方法、hashCode方法、equals方法
@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; //LocalDate类型对应数据表中的date类型private Integer deptId;private LocalDateTime createTime;//LocalDateTime类型对应数据表中的datetime类型private LocalDateTime updateTime;
}
准备Mapper接口:EmpMapper
@Mapper
public interface EmpMapper {}
预编译SQL
在Mybatis中提供的参数占位符有两种:${…} 、#{…}
-
#{…}
- 执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
- 使用时机:参数传递,都使用#{…}
-
${…}
- 拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题
- 使用时机:如果对表名、列表进行动态设置时使用
注意事项:在项目开发中,建议使用#{…},生成预编译SQL,防止SQL注入安全。
根据id查询数据
问题:查询字段数据为null
- 实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装。
- 如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。查询出来的数据为null
解决:
- 起别名
- 结果映射
- 开启驼峰命名
Mapper接口方法
配置application.properties开启自动结果映射
mybatis.configuration.map-underscore-to-camel-case=true
使用前提
- 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名
- 表中字段名:abc_xyz
- 类中属性名:abcXyz
//2.结果映射查询@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")Emp getById(Integer id);//1.起别名查询@Select("select id, username, password, name, gender, image, job, entrydate, " +"dept_id AS deptId, create_time AS createTime, update_time AS updateTime " +"from emp " +"where id=#{id}")Emp getById(Integer id);//3.手动结果映射@Results({@Result(column = "dept_id", property = "deptId"),@Result(column = "create_time", property = "createTime"),@Result(column = "update_time", property = "updateTime")})@Select("select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time from emp where id=#{id}")public Emp getById(Integer id);
单元测试
@Testpublic void testGetById(){Emp emp = empMapper.getById(1);System.out.println(emp);}
条件模糊查询
Mapper接口方法
@Select("select * from emp " +"where name like concat('%',#{name},'%') " +"and gender = #{gender} " +"and entrydate between #{begin} and #{end} " +"order by update_time desc")List<Emp> getList(String name, Short gender, LocalDate begin, LocalDate end);
单元测试
@Testpublic void testGet(){List<Emp> emps = empMapper.getList("张",(short)1,LocalDate.of(2000,1,1),LocalDate.of(2025,1,1));for (Emp emp : emps){System.out.println(emp);}}
根据主键删除数据
Mapper接口方法
//如果mapper接口方法形参只有一个普通类型的参数,#{…} 里面的属性名可以随便写//但是建议保持名字一致@Delete("delete from emp where id = #{id}")int deletById(Integer id);
单元测试
@Autowired//从Spring的IOC容器中,获取类型是EmpMapper的对象并注入private EmpMapper empMapper;@Testvoid deleteById(){Integer row = empMapper.deletById(16);System.out.println(row > 0 ? "删除成功" : "删除失败");}
添加数据
Mapper接口方法
@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})")int insert(Emp emp);
单元测试
@Testpublic void testInsert(){//创建员工对象Emp emp = new Emp();emp.setUsername("tom");emp.setName("汤姆");emp.setImage("1.jpg");emp.setGender((short)1);emp.setJob((short)1);emp.setEntrydate(LocalDate.of(2000,1,1));emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());emp.setDeptId(1);//调用添加方法Integer row = empMapper.insert(emp);System.out.println(row > 0 ? "添加成功" : "添加失败");}
主键返回
在数据添加成功后,需要获取插入数据库数据的主键,主键在数据库中是自动增长的,在java代码中并未设置主键数据
- 默认情况下,执行插入操作时,是不会主键值返回的。如果我们想要拿到主键值,需要在Mapper接口中的方法上添加一个Options注解,并在注解中指定属性useGeneratedKeys=true和keyProperty=“实体类属性名”
Mapper接口方法
@Options(useGeneratedKeys = true,keyProperty = "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})")int insert(Emp emp);
单元测试
@Testpublic void testInsert(){//创建员工对象Emp emp = new Emp();emp.setUsername("Jerry");emp.setName("杰瑞");emp.setImage("1.jpg");emp.setGender((short)1);emp.setJob((short)1);emp.setEntrydate(LocalDate.of(2000,1,1));emp.setCreateTime(LocalDateTime.now());emp.setUpdateTime(LocalDateTime.now());emp.setDeptId(1);//调用添加方法empMapper.insert(emp);System.out.println("id是:" + emp.getId());}
根据员工id修改数据
Mapper接口方法
@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}")int update(Emp emp);
单元测试
@Testpublic void testUpdate(){//要修改的员工信息Emp emp = new Emp();emp.setId(23);emp.setUsername("songdaxia");emp.setPassword(null);emp.setName("老宋");emp.setImage("2.jpg");emp.setGender((short)1);emp.setJob((short)2);emp.setEntrydate(LocalDate.of(2012,1,1));emp.setCreateTime(null);emp.setUpdateTime(LocalDateTime.now());emp.setDeptId(2);//调用方法,修改员工数据empMapper.update(emp);}
XML配置文件规范
使用Mybatis的注解方式,主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。
在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:
- XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)
- XML映射文件的namespace属性为Mapper接口全限定名一致
- XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。
XML配置步骤
第一步:创建xml文件
在resources配置文件夹下创建同包同名的xml文件
切记:在resources配置文件下创建包,包名之间使用 / 分割
第二步:在EmpMapper接口中添加抽象方法
List<Emp> getListByName(String name);
第三步:编写XML映射文件
注意:
namespace:接口全路径
id:指向接口中的抽象方法名
resultType:返回值类型
parameterType:传入参数类型
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.EmpMapper"><select id="getListByName" resultType="com.example.model.Emp" parameterType="String">select * from emp where name like concat('%',#{name},'%')</select>
</mapper>
第四步:测试
@Testpublic void testGetByName(){List<Emp> emps = empMapper.getListByName("张");for (Emp emp : emps){System.out.println(emp);}}
MybatisX的使用
MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生。
MybatisX插件安装
MybatisX使用
点击logo可以通过MybatisX快速定位
总结
使用Mybatis的注解,主要是来完成一些简单的增删改查功能。
如果需要实现复杂的SQL功能,建议使用XML来配置映射语句。