完成员工信息的增删改查操作。
准备
-- 部门管理
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', '张无忌', 2, '2.jpg', 1, '2015-01-01', 2, now(), now()),
(3, 'yangxiao', '123456', '杨逍', 1, '3.jpg', 3, '2005-05-01', 2, now(), now()),
(4, 'weiyixiao', '123456', '韦一笑', 1, '4.jpg', 2, '2007-01-01', 2, now(), now()),
(5, 'changyuchun', '123456', '常遇春', 2, '2.jpg', 2, '2012-12-05', 2, now(), now()),
(6, 'xiaozhao', '123456', '小昭', 1, '3.jpg', 1, '2013-09-05', 1, now(), now()),
(7, 'jixiaofu', '123456', '纪晓芙', 2, '7.jpg', 1, '2005-11-06', 1, now(), now()),
(8, 'zhouzhiruo', '123456', '周芷若', 2, '8.jpg', 2, '2014-11-09', 1, now(), now()),
(9, 'dingminjun', '123456', '丁敏君', 1, '9.jpg', 3, '2013-03-11', 1, now(), now()),
(10, 'zhaomin', '123456', '赵敏', 1, '10.jpg', 1, '2014-03-09', 1, now(), now()),
(11, 'luzhangke', '123456', '鹿杖客', 2, '11.jpg', 1, '2014-12-08', 1, now(), now()),
(12, 'hebiweng', '123456', '鹤笔翁', 1, '12.jpg', 1, '2008-08-01', 1, now(), now()),
(13, 'fangdongbai', '123456', '房东白', 2, '15.jpg', 2, '2015-11-01', 3, now(), now()),
(14, 'zhangsanfeng', '123456', '张三丰', 1, '12.jpg', 2, '2002-08-01', 2, now(), now()),
(15, 'yulianzhou', '123456', '俞莲舟', 1, '9.jpg', 1, '2011-03-11', 2, now(), now()),
(16, 'songyuanqiao', '123456', '宋远桥', 2, '10.jpg', 2, '2010-01-01', 2, now(), now()),
(17, 'chenyouliang', '123456', '陈友谅', 1, '17.jpg', NULL, '2015-03-21', NULL, now(), now());
第二三步与上一个文件一样,代码在上一个文件
Emp实体类
package com.example.springbootmybatis.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDate;
import java.time.LocalDate;
import java.time.LocalDateTime;
@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; // 修改时间
// 可添加构造方法、getter和setter方法
}
Mapper,加入@Mapper之后,会自动生成接口对象,并放到IOC容器管理中。
package com.example.springbootmybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EmpMapper {
}
删除
根据主键删除
数据库处理
delete from emp where id = 17;
Mybatis中实现
package com.example.springbootmybatis.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 delete(Integer id);
}
在test下进行测试
@SpringBootTest
class SpringbootMybatisApplicationTests {
@Autowired
private EmpMapper empMapper;
@Test
public void testDelete() {
empMapper.delete(17);
}
}
执行后会删除ID=17的数据。删除会返回一个int类型的数,反映影响了几个数据。
预编译SQL
配置日志输出到控制台,把下面代码加到application.properties
# 配置mybatis的日志,指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
可以更直观看到数据的处理
这叫做预编译
(1)性能更高
图上的前者需要编译三次,而后者只需编译一次。
(2)更安全,防止SQL的注入
select count(*) from emp where username = 'zhangwuji' and password = '111';/登成功/ select count(*) from emp where username = 'wuiewuiewiuew' and password = '' or '1' = '1';/被SQL的注入入侵,也能成功/
而预编译采用?来代替输入的内容,可以避免这一点。
#使用更多。$也会存在SQL的注入,而且性能低,因为直接把参数写在了命令中。
新增
数据库操作
-- 插入数据
insert into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time)
values ('Tom', '汤姆', 1, '1.jpg', 1, '2005-01-01', 1, now(), now());
因为ID时自增长的,密码是默认的,所以这两条不需要插入。
Mybatis操作
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})")
public void insert(Emp emp);
test,输入数据
@Test
public 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);
// 执行新增加员工信息操作
empMapper.insert(emp);
}
主键返回
// 新增员工
@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);
System.out.println(emp.getId());
更新
数据库操作
-- 更新数据
UPDATE emp SET
username = '',
name = '',
gender = '',
image = '',
job = '',
entrydate = '',
dept_id = '',
update_time = ''
WHERE id = 1;
Mybatis
@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);
test
@Test
public void testUpdate() {
// 构造员工对象
Emp emp = new Emp();
emp.setId(18);
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.setUpdateTime(LocalDateTime.now());
emp.setDeptId(1);
// 执行更新员工操作
empMapper.update(emp);
}
查询
数据库
select * from emp where id = 20;
mybatis
// 根据ID查询员工
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);
但是后三个数据没有封装进来,是因为下划线和驼峰命名不一样。
查询时数据封装
第一中方法就是起别名。
第二种Result手动封装
第三种,自动映射
# 开启mybatis的驼峰命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true
查询中的字符串拼接函数concat
-- 条件查询员工
select * from emp
where name like '%张%'
and gender = 1
and entrydate between '2010-01-01' and '2020-01-01'
order by update_time desc;
@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);// #{name}表示参数,但是?不能出现在参数中。所以使用${name}代替。
@Test
public void testList() {
List<Emp> empList = empMapper.list("张", (short) 1,
LocalDate.of(2010, 1, 1), LocalDate.of(2020, 1, 1));
System.out.println(empList);
}
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);