介绍
新手程序员一枚,渴望成为大神,来点关注来点赞,给我介绍几个大神也行,球球了。
主要记录自己的学习过程,将之前的笔记进行整理并分享一下,有错误请指出,谢谢各位大佬爷们的观看。
下面开始分享我的笔记
概述
-
持久层框架
-
简化JDBC开发
-
网站~ http://www.mybatis.cn/mybatis/index.html
入门
-
需求
-
使用Mybatis查询所有用户数据
-
-
步骤
-
创建springboot工程,建立数据库表user,实体类User
-
引入相关依赖(Mybatis),配置Mybatis(数据库连接信息)
-
编写SQL语句(注解\XML)
-
-
实现
-
常见springboot项目时候候选Mybatis和mysql驱动
-
package com.testpeople.pojo; import org.apache.ibatis.javassist.runtime.Inner; public class User { private Integer id; private String name; private Short age; private Short gender; private String phone; public User() { } public User(Integer id, String name, Short age, Short gender, String phone) { this.id = id; this.name = name; this.age = age; this.gender = gender; this.phone = phone; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Short getAge() { return age; } public void setAge(Short age) { this.age = age; } public Short getGender() { return gender; } public void setGender(Short gender) { this.gender = gender; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + ", gender=" + gender + ", phone='" + phone + '\'' + '}'; } }
-
-- 创建mybatis 数据库
-- 在库中建立下表并插入数据
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID',
`name` varchar(100) DEFAULT NULL COMMENT '姓名',
`age` tinyint unsigned DEFAULT NULL COMMENT '年龄',
`gender` tinyint unsigned DEFAULT NULL COMMENT '性别, 1:男, 2:女',
`phone` varchar(11) DEFAULT NULL COMMENT '手机号',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
INSERT INTO `user` VALUES (1,'白眉鹰王',55,1,'18800000000');
INSERT INTO `user` VALUES (2,'金毛狮王',45,1,'18800000001');
INSERT INTO `user` VALUES (3,'青翼蝠王',38,1,'18800000002');
INSERT INTO `user` VALUES (4,'紫衫龙王',42,2,'18800000003');
INSERT INTO `user` VALUES (5,'光明左使',37,1,'18800000004');
INSERT INTO `user` VALUES (6,'光明右使',48,1,'18800000005');
-
配置mybatis文件application.properties
#配置数据源连接信息——四要素 #驱动配置 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #数据库连接地址 spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai #数据库用户名 spring.datasource.username=root #连接密码 spring.datasource.password=123456 #注意仔细配置这个文件否则会报错 #还要注意版本问题
-
创建SQL接口
-
创建接口文件
-
添加@Mapper注解
-
@Mapper //运行时。会自动生成该接口的实现类对象(代理对象),并将该对象交给IOC容器管理.
-
添加查询操作的方法
-
//查询所有客户信息 @Select(value = "select * from user") //注解表示这是查询方法 public List<User> findAll();
- 编写测试类代码
-
在测试类中编写测试代码
-
class SpringbootMybatisQuickstartApplicationTests { //由于添加了@Mapper注解,框架会自动实现接口,对象被Bean管理,所以只需要依赖注入即可 @Autowired private UserMapper userMapper; //定义测试查询语句方法 public void testFindAll(){ System.out.println("查询所有用户信息"); userMapper.findAll().forEach(System.out::println); List<User> userList = userMapper.findAll(); //stream流方式输出。 userList.stream().forEach(user->{ System.out.println(user); }); } }
-
效果
-
-
-
idea中配置SQL提示
-
选中语句并单击下图,并选中正确语言
-
idea中配置与MySQL数据库的连接
-
正常连接数据库需要指明那个数据库
-
-
JDBC介绍
-
使用java语言操作关系型数据库的一套API.
-
各个数据库厂商实现驱动Jar包
-
我们使用接口编程
数据库连接池
-
一个负责分配、管理数据库连接的容器。
-
允许应用程序使用一个现有的数据库连接,不需要重新建立一个。
-
有一个连接时间,长时间不用会收回连接。
-
需要实现DataSiurce接口
-
产品:C3P0、DBCP、Druid、Hikari(默认)。
-
切换只需要用Mvaen引入包即可。
lombok
-
解决实体类代码臃肿问题
-
添加lombok插件(idea插件自带)
-
添加依赖
-
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
-
添加注解
-
@Data //getter setter toString hashCode方法 @AllArgsConstructor //全参构造 @NoArgsConstructor //无参构造
效果如上
基础
需求
-
完成员工操作
-
数据库(mybatis)
-
准备
-
CREATE TABLE `user` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(100) DEFAULT NULL COMMENT '姓名', `age` tinyint unsigned DEFAULT NULL COMMENT '年龄', `gender` tinyint unsigned DEFAULT NULL COMMENT '性别, 1:男, 2:女', `phone` varchar(11) DEFAULT NULL COMMENT '手机号', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表'; INSERT INTO `user` VALUES (1,'白眉鹰王',55,1,'18800000000'); INSERT INTO `user` VALUES (2,'金毛狮王',45,1,'18800000001'); INSERT INTO `user` VALUES (3,'青翼蝠王',38,1,'18800000002'); INSERT INTO `user` VALUES (4,'紫衫龙王',42,2,'18800000003'); INSERT INTO `user` VALUES (5,'光明左使',37,1,'18800000004'); INSERT INTO `user` VALUES (6,'光明右使',48,1,'18800000005'); CREATE TABLE if not exists `dept` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID', `name` varchar(10) NOT NULL COMMENT '部门名称', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='部门表'; INSERT INTO `dept` VALUES (1,'学工部','2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `dept` VALUES (2,'教研部','2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `dept` VALUES (3,'咨询部','2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `dept` VALUES (4,'就业部','2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `dept` VALUES (5,'人事部','2023-12-28 20:23:44','2023-12-28 20:23:44'); CREATE TABLE if not exists `emp` ( `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `username` varchar(20) NOT NULL COMMENT '用户名', `password` varchar(32) DEFAULT '123456' COMMENT '密码', `name` varchar(10) NOT NULL COMMENT '姓名', `gender` tinyint unsigned NOT NULL COMMENT '性别, 说明: 1 男, 2 女', `image` varchar(300) DEFAULT NULL COMMENT '图像', `job` tinyint unsigned DEFAULT NULL COMMENT '职位, 说明: 1 班主任,2 讲师, 3 学工主管, 4 教研主管, 5 咨询师', `entrydate` date DEFAULT NULL COMMENT '入职时间', `dept_id` int unsigned DEFAULT NULL COMMENT '部门ID', `create_time` datetime NOT NULL COMMENT '创建时间', `update_time` datetime NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='员工表'; INSERT INTO `emp` VALUES (1,'jinyong','123456','金庸',1,'1.jpg',4,'2000-01-01',2,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (2,'zhangwuji','123456','张无忌',1,'2.jpg',2,'2015-01-01',2,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (3,'yangxiao','123456','杨逍',1,'3.jpg',2,'2008-05-01',2,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (4,'weiyixiao','123456','韦一笑',1,'4.jpg',2,'2007-01-01',2,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (5,'changyuchun','123456','常遇春',1,'5.jpg',2,'2012-12-05',2,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (6,'xiaozhao','123456','小昭',2,'6.jpg',3,'2013-09-05',1,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (7,'jixiaofu','123456','纪晓芙',2,'7.jpg',1,'2005-08-01',1,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (8,'zhouzhiruo','123456','周芷若',2,'8.jpg',1,'2014-11-09',1,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (9,'dingminjun','123456','丁敏君',2,'9.jpg',1,'2011-03-11',1,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (10,'zhaomin','123456','赵敏',2,'10.jpg',1,'2013-09-05',1,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (11,'luzhangke','123456','鹿杖客',1,'11.jpg',5,'2007-02-01',3,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (12,'hebiweng','123456','鹤笔翁',1,'12.jpg',5,'2008-08-18',3,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (13,'fangdongbai','123456','方东白',1,'13.jpg',5,'2012-11-01',3,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (14,'zhangsanfeng','123456','张三丰',1,'14.jpg',2,'2002-08-01',2,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (15,'yulianzhou','123456','俞莲舟',1,'15.jpg',2,'2011-05-01',2,'2023-12-28 20:23:44','2023-12-28 20:23:44'); INSERT INTO `emp` VALUES (18,'Tom1','123456','汤姆1',1,'1.jpg',1,'2000-01-01',1,'2023-12-29 08:31:43','2023-12-29 09:03:51'); INSERT INTO `emp` VALUES (19,'Tom2','123456','汤姆2',1,'1.jpg',1,'2000-01-01',1,'2023-12-29 08:35:50','2023-12-29 08:35:50'); INSERT INTO `emp` VALUES (20,'Tom3','123456','汤姆3',1,'1.jpg',1,'2000-01-01',1,'2023-12-29 08:37:47','2023-12-29 08:37:47');
-
员工实体类
-
package com.testpeople.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.time.LocalDate; @Data @NoArgsConstructor @AllArgsConstructor public class Emp { private Integer 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;//部门编号 private LocalDate createdate;//创建日期 private LocalDate updatedate;//更新日期 }
-
Mapper接口
-
package com.testpeople.mapper; import org.apache.ibatis.annotations.Mapper; @Mapper public interface EmpMapper { }
通过注解的方式配置SQL
-
删除
-
接口方法
-
//删除方法~根据员工ID删除数据 //删除员工 @Delete(value = "delete from mybatis.emp where id=#{id}") public void deleteEmp(Integer id);
-
占位符
-
#{...}
-
生成预编译SQL,会自动设置参数值
-
使用时机:参数传递。
-
-
${...}
-
拼接SQL,直接将参数拼接到SQL中,存在SQL注入问题。
-
使用时机:对表名、列名进行动态设置时使用。
-
-
-
测试
-
//测试方法 //删除操作类型 @Autowired private EmpMapper empMapper; //删除方法 @Test public void testDeleteEmp(){ System.out.println("删除ing"); Integer num = empMapper.deleteEmp(19); System.out.println("删除"+num+"条数据"); }
-
MyBatis日志信息配置
-
位置在Applicants.properties文件中
-
#日志输出到控制台 mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
-
预编译SQL
-
-
优势
-
性能高
-
防止SQL注入
-
通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。
-
-
' or'1'=' 1
新增
-
接口方法
-
//添加员工 @Insert(value = "insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, update_time)\n" + " values (#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptID},#{createdateTime},#{updatedateTime});") public Integer addEmp(Emp emp);
-
注意
-
Value中添加的实体类的属性名。
-
-
测试
-
//测试方法 @Test public void testAddEmp(){ 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(2020, 1, 1)); emp.setDeptId(1); emp.setCreatedateTime(LocalDateTime.now()); emp.setUpdatedateTime(LocalDateTime.now()); Integer num = empMapper.addEmp(emp); System.out.println("添加"+num+"条数据"); }
-
效果
-
Tips
-
主键返回
-
默认情况下,不会返回主键
-
实现:添加注解
-
//在需要的方法上添加此注解 @Options(useGeneratedKeys = true, keyProperty = "id") // 添加员工后,返回主键
-
-
更新
-
接口方法
-
//更新员工 @Update(value = "update emp set username=#{username}, name=#{name}, gender=#{gender}, image=#{image}," + "job=#{job}, entrydate=#{entrydate}, dept_id=#{deptId}, update_time=#{updatedateTime} where id=#{id};") public Integer updateEmp(Emp emp);
-
测试
-
//更新方法test @Test public void testUpdateEmp(){ System.out.println("更新数据中"); Emp emp = new Emp(); emp.setId(22); emp.setUsername("Tom"); emp.setName("汤姆"); emp.setImage("1.jpg"); emp.setGender((short) 2); emp.setJob((short) 2); emp.setEntrydate(LocalDate.of(2024, 1, 1)); emp.setDeptId(1); emp.setUpdatedateTime(LocalDateTime.now()); Integer num = empMapper.updateEmp(emp); System.out.println("更新"+num+"条数据"); }
-
效果
查询
根据ID查询员工
-
接口方法
-
//查询员工(根据ID) // @Select(value = "select * from emp where id = #{id};") // public Emp findEmpById(Integer id); //解决mybatis的封装问题 //方案一: 使用别名 // @Select(value = "select id, username, password, name, gender, image, job, entrydate, dept_id as deptID, create_time as createdateTime, update_time as updatedateTime from emp where id = #{id};") // public Emp findEmpById(Integer id); //方案二: 使用@results 和 @result 手动封装 // @Results(value = { // @Result(property = "deptId", column = "dept_id"), // @Result(property = "updatedateTime", column = "update_time"), // @Result(property = "createdateTime", column = "create_time"), // }) // @Select(value = "select * from emp where id = #{id};") // public Emp findEmpById(Integer id); // //方案三:Mybatis 的驼峰自动命名开关(配置application.properties) //a_colums -> aColums @Select(value = "select * from emp where id = #{id};") public Emp findEmpById(Integer id);
-
测试
-
//查询方法test @Test public void testFindEmpById(){ System.out.println("查询数据中"); Emp emp = empMapper.findEmpById(1); System.out.println(emp); }
-
注意
-
封装问题(默认为相同字段名自动封装)
-
解决
-
起别名(让别名和属性名相同)
-
//方案一: 使用别名 @Select(value = "select id, username, password, name, gender, image, job, entrydate, dept_id as deptID, create_time as createdateTime, update_time as updatedateTime from emp where id = #{id};") public Emp findEmpById(Integer id);
-
通过注解( 使用@results 和 @result 手动封装)
-
-
-
//方案二: 使用@results 和 @result 手动封装 @Results(value = { @Result(property = "deptId", column = "dept_id"), @Result(property = "updatedateTime", column = "update_time"), @Result(property = "createdateTime", column = "create_time"), }) @Select(value = "select * from emp where id = #{id};") public Emp findEmpById(Integer id); //注意 //property为实体类名 column为表的字段值
-
打开Mybatis中驼峰自动命名开关
-
#开启驼峰命名开关 a_colums->aColums mybatis.configuration.map-underscore-to-camel-case=true
根据条件查询
-
接口方法
-
//条件查询员工 @Select(value = "select * from emp where name like '%${name}%' and gender = #{gender} and" + " entrydate between #{begin} and #{end} order by update_time desc;") public List<Emp> findEmpByCondition(String name, Short gender, LocalDate begin, LocalDate end); //注意#{}不能封装到''中 ,预编译会把#{}变成?所有可以使用${}拼接。
-
注意(存在注入问题)
-
通过MySQL的字符串拼接函数进行拼接。
-
测试
-
//查询方法test(条件查询) @Test public void testFindEmpByCondition(){ System.out.println("查询数据中"); List<Emp> emps = empMapper.findEmpByCondition("张",(short) 1,LocalDate.of(2000,1,1),LocalDate.of(2024,1,1)); emps.forEach(System.out::println); System.out.println("查询数据结束"); }
-
效果
-
同通过XML文件的方式配置SQL
规范
-
XML文件名与Mapper接口名一致,并且将文件与Mapper接口放在一个包下(同包同名)
<?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>
<!--此处定义语句-->
</mapper>
-
XML文件中的namespace属性与Mapper接口全限定名一致
-
<mapper namespace="com.testpeople.mapper.EmpMapper"> </mapper> <!--注意标题-->
-
XML文件中的sql语句的id与Mapper接口中的方法名一致,反返回值一致。
-
<select id="findEmpByConditionXml" resultType="com.testpeople.pojo.Emp"> </select>
- 效果
插件
-
MybatisX
动态SQL
-
随着用户的输入或者外部条件的变化而变化的SQL语句。
标签
<if>
入门
-
用于判断条件是否成立。
-
使用test进行判断
-
条件为True则拼接
-
<!-- 动态SQL条件查询--> <select id="findEmpByConditionXml" resultType="com.testpeople.pojo.Emp"> select * from emp where <if test="name != null"> name like concat('%', #{name}, '%') </if> <if test="gender != null"> and gender = #{gender} </if> <if test="bengin != null ans end != null"> and entrydate between #{begin} and #{end} </if> order by update_time desc; </select>
-
注意
-
以上会出现问题,条件1不成立,语法错误
-
可以用<where>标签
-
<!-- 动态SQL条件查询--> <select id="findEmpByConditionXml" resultType="com.testpeople.pojo.Emp"> select * from emp <where> <if test="name != null"> name like concat('%', #{name}, '%') </if> <if test="gender != null"> and gender = #{gender} </if> <if test="begin != null and end != null"> and entrydate between #{begin} and #{end} </if> </where> order by update_time desc; </select>
-
测试效果
-
//动态SQL @Test public void testFindEmpByConditionXml(){ System.out.println("查询数据中"); List<Emp> emps = empMapper.findEmpByConditionXml("周",null,null,null); emps.forEach(System.out::println); System.out.println("查询数据结束"); }
-
案例
需求
-
完善更新员工功能,若有值,则更新,否则不更新
实现
-
接口方法
-
//动态更新员工 //动态SQL public Integer updateEmp2(Emp emp);
-
XML配置文件
-
<!-- 员工更新--> <update id="updateEmp2"> update 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 != null">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> where id = #{id}; </update>
-
注意
-
上述配置会出现bug(sql语法错误)
-
拼接问题
-
使用<set>标签,和<where>差不多
-
<!-- 员工更新--> <update id="updateEmp2"> update 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 != null">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 public void testUpdateEmp2(){ System.out.println("更新数据中"); Emp emp = new Emp(); emp.setId(22); emp.setUsername("Tom0"); emp.setUpdateTime(LocalDateTime.now()); Integer num = empMapper.updateEmp2(emp); System.out.println("更新"+num+"条数据"); }
- 效果
-
<foreach>
需求
-
批量删除
-
实现
-
接口
-
//批量删除 public Integer deleteEmpBatch(List<Integer> ids);
-
XML文件配置
-
<!-- 批量删除--> <!-- collection:集合 item:集合中的元素 separator:分隔符 open:前缀遍历开始前拼接的SQL close:后缀遍历开始后拼接的SQL --> <delete id="deleteEmpBatch"> delete from emp where id in <foreach collection = "ids" item = "id" separator = "," open = "(" close = ")"> #{id} </foreach> </delete>
-
测试
-
//测试批量删除 @Test public void testDeleteEmpBatch(){ System.out.println("批量删除数据中"); List<Integer> ids = Arrays.asList(18,22,23,24); Integer nums = empMapper.deleteEmpBatch(ids); System.out.println(nums); }
效果
-
<sql><include>
功能
-
用于封装重复的SQL语句
-
<!-- 封装--> <sql id="selectEmp"> select id,username,name,gender,image,job,entrydate,dept_id,create_time,update_time from emp </sql> <!-- 原来的位置引用--> <include refid="selectEmp"/>
总结
以上是学习的第十弹笔记,也是后端开始的第六弹笔记,感兴趣的关注一手,后面会慢慢更新笔记。
项目位置!!!!!
https://gitee.com/zsjnew/admin_web_project.git