@NoArgsConstructor
@Data
public class Emp {
private Integer id;
private String username;
private String password;
private String name;
private Short gender;
private Short job;
private LocalDate entryDate;
private Short deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
6. 准备Mapper接口EmpMapper用于写sql语句,后面演示
>
> 注意:
>
>
> 1. 若jdk为11,springboot的起步依赖版本号最好为2.7.5,运行报错时,可以将MyBatis的起步依赖版本改为2.2.2,可能是因为MyBatis版本冲突。
> 2. 实体类中的数据类型最好用引用类型Integer,因为引用类型才能赋值为空,默认也为空,后面要用。字段类型要与实体类型对应,其中varchar对应String,date对应LocalDate,datetime对应LocalDateTime。
> 3. mapper层就是dao层,Mybatis框架中sql语句是写在Mapper类型接口中的,而@Mapper注解用于声明该接口为Mapper类型接口,同时也声明该接口实现类为Bean对象,启动时自动创建该接口的实现类并交给IOC容器管理。
>
>
>
##
## 配置SQL提示
1、选中SQL语句右键->Show Context Actions->Inject language or reference->MySQL。
作用:SQL语法检查
2、导入数据库。
作用:有SQL提示
![2377d6cf0823461f9aa2148b457cfc4b.png](https://img-blog.csdnimg.cn/direct/2377d6cf0823461f9aa2148b457cfc4b.png)
![bff1a51f3b304eeaa1e0586c29d9868f.png](https://img-blog.csdnimg.cn/direct/bff1a51f3b304eeaa1e0586c29d9868f.png)
## 删除
// 根据员工id删除员工信息
EmpMapper接口中delete()方法的实现
@Mapper
public interface EmpMapper {
// 根据传入的id删除员工
@Delete("delete from emp where id = #{id}")
void deleteById(Integer id);
}
测试类测试
@SpringBootTest
class Test02ApplicationTests {
// 前面说了添加@Mapper注解后,启动时会自动创建该接口实现类并交给IOC容器管理
// 以自动注入方式创建EmpMapper接口实现类对象
@Autowired
EmpMapper empMapper;
@Test
void testDelete(){
// 调用该对象的删除方法,删除id为27的员工
empMapper.deleteById(27);
}
}
>
> 注意:
>
>
> 1、#{..}为参数占位符,里面的参数最好与方法的形参名相同,表示将方法形参值传入进去。
>
>
> 2、返回值类型若为Integer,则表示影响的记录数。
>
>
>
## 预编译SQL
**Mybatis****日志**
配置mybatis的日志,指定输出到控制台,配置到resources\application.properties文件中
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
**普通编译SQL**
参数占位符${…},每次运行都要先编译,编译时,${…}参数占位符用传入的参数代替并拼接到SQL语句中,再执行SQL。
如:select\*from emp where id = ${id}
编译时,用传入参数直接代替${id}拼接到SQL语句中,若id为 1 and name = ‘张三丰’,拼接后就为select\*from emp where id = 1 and name = ‘张三丰’ 违背了SQL根据id查询。
**SQL****注入**
SQL注入是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器的攻击的方法。
如:账号登录
select count(\*) from emp where username = ${username} and password = ${password}
账号随便写,密码传入 abc or 1,编译拼接为
select count(\*) from emp where username = aaa and password = abc or 1
这样就会导致无论怎样都会登录成功!
普通编译SQL使用${…}就可能会造成SQL注入。
**预编译SQL**
参数占位符#{…},预编译SQL会进行先编译,#{…}参数占位符用?,再传入参数代替?来执行,只需编译一次。
如:@Delete("delete from emp where id = #{id}")
int delete(Integer id);
先预编译为delete from emp where id = ?,只编译一次
再传入参数id代替?来执行SQL
>
> 特点:
>
>
> 1、提升性能(只编译一次)。
>
>
> 2、防止SQL注入,预编译时#{…}用?代替,?只被认定为一个参数,无论怎么写系统都会把认定为一个参数,而不是认定为SQL片段,所以不会造成SQL注入。
>
>
>
**参数占位符**
**#{…}**
执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值
使用时机:参数传递,都使用#{…},几乎都使用#{…}占位符
${…}
拼接SQL,直接将参数拼接在SQL语句中,存在SQL注入问题
使用时机:如果对表名、列表进行动态设置时使用
##
## 新增
EmpMapper接口实现
// 将主键id返回并封装到实体类Emp对象id属性中,看自己需要
@Options(keyProperty = "id",useGeneratedKeys = true)
@Insert("insert into emp(id, username, password, name, gender, job, entry_date, dept_id, create_time, update_time) VALUES (" +
"null,#{username},#{password},#{name},#{gender},#{job},#{entryDate},#{deptId},#{createTime},#{updateTime})")
void insert(Emp emp);
测试类测试
@Autowired
EmpMapper empMapper;// 获取EmpMapper接口实现类对象
@Test
void testInsert(){
String username = "zhansanfeng";
String password = "123456";
String name = "张三丰";
Short gender = 1;
Short job = 1;
LocalDate entryDate = LocalDate.of(2015,9,15);
Short deptId = 2;
LocalDateTime createTime = LocalDateTime.now();
LocalDateTime updateTime = LocalDateTime.now();
// 将用户信息封装到实体类对象中
Emp emp = new Emp(null,username,password,name,gender,job,entryDate,deptId,createTime,updateTime);
// 将该实体对象插入
empMapper.insert(emp);
}
>
> 注意:
>
>
> 1、方法形参最好传递Emp对象,SQL中#{…}可以自动获取形参对象的属性。
>
>
> 2、对象的属性是驼峰命名,如:deptId,所以获取对象属性时别写错了。
>
>
> 3、表字段与对象属性类型要匹配,其中:date对应LocalDate,datetime对应LocalDateTime。
>
>
> 4、若方法的返回值类型为整数,则返回值为插入的记录数。
>
>
> 5、由于id为主键且自增,所以直接赋值为null就行,不用管它。
>
>
>
**新增(主键返回)**
描述:在数据添加成功后,需要获取插入数据库数据的主键。
如:添加套餐数据时,还需要维护套餐菜品关系表数据。因为关系表的维护需要主表的主键。
在SQL语句上添加@Options(keyProperty = "id",useGeneratedKeys = true)
其中keyProperty属性值*代表*将主键封装到实体类中哪个属性,useGeneratedKeys属性值为true代表需要主键返回。
## 更新
思路:将更新的用户信息封装到实体类对象,再将实体类对象传入进行用户更新。
Mapper接口实现
// 根据主键修改员工信息
@Update(“update emp set username = #{username},name = #{name},gender = #{gender},” +
"job = #{job},entry_date = #{entryDate},dept_id = #{deptId},update_time " +
“= #{updateTime} where id = #{id};”)
void update(Emp emp);
测试类测试
@Autowired
EmpMapper empMapper;// 获取EmpMapper接口实现类对象
@Test
void testUpdate(){
// 一定要封装主键id,因为是根据id更新的
Integer id = 29;
String username = "xvshiyou";
String password = "12345";
String name = "许世友";
Short gender = 1;
Short job = 2;
LocalDate entryDate = LocalDate.of(2012,5,6);
Short deptId = 3;
LocalDateTime createTime = LocalDateTime.now();
LocalDateTime updateTime = LocalDateTime.now();
// 封装用户的更新信息
Emp emp = new Emp(29,username,password,name,gender,job,entryDate,deptId,createTime,updateTime);
// 更新
empMapper.update(emp);
}
>
> 注意:
>
>
> 1、形参为修改后的员工emp,emp的id一定要正确赋值,因为是根据id修改员工信息
>
>
> 2、缺点:不能修改单个信息,每一次都是更新用户所有信息,如当只修改name属性时,其余属性就默认为null,则更新时,这些属性就会被修改为null,不符合业务逻辑。
>
>
> 3、这里只是简了Mybatis的update语句和更新逻辑,之后再进行优化。
>
>
>
##
## 查询
EmpMapper接口实现
// 查询所有员工信息
@Select("select * from emp")
List<Emp> list();
// 根据主键id查询员工
@Select("select * from emp where id = #{id}")
Emp listById(Integer id);
测试类测试与上面一样,只需调用该方法并接收其返回值即可。
>
> 注意:
>
>
> 1、Select语句会自动将查询的信息封装到返回值里面。
>
>
> 2、查询所有员工,肯定有多条员工信息,所以用Emp的集合进行封装并返回。
>
>
> 3、根据主键id查询,id是唯一的,若id存在,查询的员工记录只有一条,所以只需Emp进行封装并返回即可。
>
>
>
##
## 数据封装
**前面讲了Select语句会将查询的信息自动封装到返回值Emp实体类对象中**
表的字段:id、username、password、name、dept\_id、entry\_date ...
实体类属性:id、username、password、name、deptId、entryDate ...
我们理想中Select语句查询的字段id值封装到属性id中,字段username值封装到属性username中,字段dept\_id值封装到属性deptId中。
**Mybatis如何实现呢?**
* 实体类属性名和数据库查询返回的字段名一致,不区分大小写,mybatis会自动封装。即表字段id自动封装到实体类对象属性id中。
* 如果实体类属性名和数据库返回的字段名不一致,不能自动封装则属性值为默认值。即表字段dept\_id与实体类属性deptId不一致,无法自动封装,则deptId就为默认值null。
* 属性名为驼峰命名deptId,字段名为下划线dept\_id,不一致,在封装时要注意。
**解决:**
方案一:给字段取别名,让别名与实体属性保持一致。
// 查询所有员工信息
@Select("select id, username, password, name, gender, job, entry_date entryDate, " +
"dept_id deptId, create_time createTime, update_time updateTime from emp")
List<Emp> list();
方案二:通过@Results,@Result注解手动映射封装。
@Results({
@Result(column = "dept_id",property = "deptId"),
@Result(column = "entry_date",property = "entryDate"),
@Result(column = "create_time",property = "createTime"),
@Result(column = "update_time",property = "updateTime")
})
// 查询所有员工信息
@Select("select id, username, password, name, gender, job, entry_date, " +
"dept_id, create_time, update_time from emp")
List<Emp> list();
其思路就是将不能自动封装的字段如dept\_id,通过@Result注解手动映射封装。
其中column属性值为字段名,property属性值为要封装到的属性名。
方案三:开启mybatis的驼峰命名自动映射开关 --- a\_cloumn ----> aCloumn
![](https://img-blog.csdnimg.cn/img_convert/9a8cb5f8c0ec69e6499adead0da6e95b.png)
最全的Linux教程,Linux从入门到精通
======================
1. **linux从入门到精通(第2版)**
2. **Linux系统移植**
3. **Linux驱动开发入门与实战**
4. **LINUX 系统移植 第2版**
5. **Linux开源网络全栈详解 从DPDK到OpenFlow**
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/59742364bb1338737fe2d315a9e2ec54.png)
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)
**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/topics/618542503)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**