此处是根据需求实现基本操作
上面这里涉及到了条件分页查询,还有增加和批量删除员工信息,右边编辑就是先查询后更新操作,叫做查询回显,然后在原有基础上进行更新
环境准备
在下面的入门案例的整体环境下把数据库表换成empSpringBoot——基于SpringBoot整合Mybatis的入门案例+sql提示配置+lombok工具包介绍_北岭山脚鼠鼠的博客-CSDN博客
使用如下的建表语句
-- 部门管理
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());
准备一个对应的实体类,实体类当中有三个属性要使用驼峰命名法,因为在数据库当中有三个属性名中有下划线
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer id; //ID
private String username; //用户名
private String password; //密码
private String name; //姓名
private Short gender; //性别, 1 男, 2 女
private String image; //图像url
private Short job; //职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师'
private LocalDate entrydate; //入职日期
private Integer deptId; //部门ID
private LocalDateTime createTime; //创建时间
private LocalDateTime updateTime; //修改时间
}
准备一个EmpMapper接口
@Mapper
public interface EmpMapper {
}
运行单元测试如果出现如下错误
Lombok requires enabled annotation processing
lombok 需要启用注释处理
首先可以在下面这里勾选启用注解处理然后重启IDEA
其次不行就去插件哪里更新lombok
增删改查的通用流程
在EmpMapper中新建一个方法定义sql语句——>在test目录下进行测试
删除
这个就是根据每个员工的id删除。
注意事项:如果这里的方法形参中只有一个属性,可以直接用属性名写在参数占位符#{}里面,当有多个参数时需要用到一个@Param()注解错误的信息,只有在springboot1.X版本或者单独使用mybatis时才需要使用@Param注解。
因为在对mapper接口编译时不会保留方法的形参名称
//根据ID删除数据
@Delete("delete from emp where id = #{id}")
public void delete(Integer id);
//public int delete(Integer id);
@Delete("delete from emp where id = #{id} and name= #{name}")
public int delete(@Param("id") Integer id,@Param("name") String name);
delete的单元测试
此处可以设置返回值为int,删除成功就返回1,删除失败就返回0,返回的是受影响的行数
@Test
public void testDelete(){
System.out.println(empMapper.delete(17));
}
要想看见上面操作的过程,可以配置日志输出
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
在预编译SQL中的?就是EmpMapper中的#{},下面的17就是要传进去的参数。
最后整条一起发给数据库去执行。
然后测试就可以看见控制台输出如下
优势:
原本的sql语句执行会先检查缓存是否存在同样的语句,有就直接执行,没有就编译后缓存,比如上面的三条就要编译三次,而预编译如图很明显了,只需要编译一次。
安全性
密码如上进行输入时执行了下面这条sql语句
此时整条sql语句已经发生了变化,添加了一个新的或条件'1'='1',这样无论怎么样都可以返回结果为1,太好玩了。
SQL注入能够成功的原因就是参数被直接拼接在了sql语句当中,用了预编译sql就可以用?防止sql注入
参数占位符
增加
增加一个新的员工时主键的值是不需要设定的,而且这里传进来的参数可以是一个对象,参数占位符里面直接写属性名就可以了
//新增员工
@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})")
public void insert(Emp emp);
单元测试类当中
@Test
public void testInsert(){
//构造员工对象
Emp emp = new Emp();
emp.setUsername("北岭山脚鼠鼠");
emp.setName("yhy");
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(emp.getId());
}
控制台输出如下(已经添加了@Options注解)
新增(主键返回)
加上一个@Options注解,里面有两个属性可以把获取到的主键再封装会对象当中
更新
这种情况通常都要先根据id查询用于页面回写,然后再将更新的数据写进去
更新数据
@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 update(Emp emp);
查询(根据ID查询)
Mapper内
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);
单元测试
//根据ID查询员工
@Test
public void testGetById(){
Emp emp = empMapper.getById(18);
System.out.println(emp);
}
在下面的输出中可以看见有三个名称里有下划线的没有查询到,但是在数据库里面是有值的。
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,@Result注解手动映射封装)
//方案二: 通过@Results, @Result注解手动映射封装
@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的驼峰命名自动映射开关)
在配置文件中加上这一句
mybatis.configuration.map-underscore-to-camel-case=true
然后就可以用回最开始的方法了
查询(条件查询)
有如下需要
Mapper中
这里使用对象传参的话没有开始时间和结束时间这两个属性,其中name要用到模糊查询,不能让#{}生成的?出现在'%?%'之内,所以这里就用了字符串拼接的${}
解决方案一(使用${})
// 条件查询员工
// 方式一
@Select("select * from emp where name like '%${name}%' and gender = #{gender} and " +
"entrydate between #{begin} and #{end} order by update_time desc ")
public List<Emp> list(String name, Short gender, LocalDate begin , LocalDate end);
单元测试
//根据条件查询员工
@Test
public void testList(){
//List<Emp> empList = empMapper.list("张", (short) 1, LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
//List<Emp> empList = empMapper.list("张", null, null, null);
//List<Emp> empList = empMapper.list("张", (short)1, null, null);
//List<Emp> empList = empMapper.list(null, (short)1, null, null);
List<Emp> empList = empMapper.list(null, null, null, null);
System.out.println(empList);
}
解决方案二(concat函数){推荐使用}
为了解决上面的sql注入问题可以使用一个字符串拼接函数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<Emp> list(String name, Short gender, LocalDate begin , LocalDate end);
到此结束
下面是基于XML映射文件开发CURD的链接
未完待续