一.mybatis
1.1 mybatis简介
MyBatis 是一款优秀的持久层框架
,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
总结:
mybayis是一款优秀的持久层框架
在内部封装了JDBC,简化了操作数据库的过程- 映射:数据库中的表与POJO中的类----映射
表中的字段与类-----映射
1.2 入门案例
1.2.1 编辑pom.xml配置文件
<!--mybatis依赖包-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!--jdbc依赖包-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--添加lombok的包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
1.2.2 lombok插件安装
1.2.2.1 lombok介绍
说明: pojo对象中必须添加get/set/toString等常规方法,但是该方法写起来繁琐,但是又必须添加. 所以可以引入lombok插件动态生成上述的方法.
1.2.3 导入jar包
<!--添加lombok的包-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
1.2.4 编辑POJO
package com.jt.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.Alias;
import java.io.Serializable;
@Data //动态生成get/set/toString/equals/hashCode/等
@Accessors(chain = true)//开启链式加载 重写set方法
@NoArgsConstructor //无参构造
@AllArgsConstructor //全参构造
//@Alias("User") //标识注解 该注解我们需要一个一个标识
public class User implements Serializable { //序列化以后扩展方便
private Integer id;
private String name;
private Integer age;
private String sex;
/*为什么pojo类要实现序列化
1、序列化就是一种用来处理对象流的机制,所谓对象流就是将对象的内容进行流化。
可以对流化后的对象进行读写操作,也可以在网络之间传输,需要实现Serializable接口,
该接口没有需要实现的方法,只是为了表示对象是可以序列化的。序列化是将对象转换为容易传输的格式的过程。
2、是对象永久化的一种机制,在程序终止后,这些对象仍然存在,可以在程序再次启动之后读取这些对象的值,
也可以在其他程序利用这些保存下来的值。
3、只有序列化的对象才可以存储在存储设备上
* */
/** public User setId(Integer id){
this.id=id;
return this;//指代当前对象! 运行期有效
}
public void xxx(){
User user=new User();
//链式加载规则.重写set方法,要求返回当前的对象user(链式结构)
user.setId(100).setName("xxx").setAge(18).setSex("女");
}*/
}
1.2.5 编辑Mapper接口
@Mapper //将接口交给Spring容器管理 Map<userMapper,JDK代理对象>
//@Repository //将持久层交给Spring容器管理
public interface UserMapper {
//查询所有的用户信息
List<User> findAll();
}
1.2.6 编辑Mapper的映射文件UserMapper.xml
核心作用: 编辑操作数据库的Sql
<?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">
<!--
调用流程:
1.编辑Mapper接口 编辑接口方法
2.映射文件与Mapper接口绑定 namespace
-->
<mapper namespace="com.jt.mapper.UserMapper">
<!--
1.id与接口的方法名称绑定
2. 回顾:JDBC->resultSet->遍历结果集->手动封装对象
3. resultType: mybatis自动的将结果集的数据封装为对象
如果返回值List集合,则自动封装为List,User充当其中的泛型对象
如果返回值User对象.则直接返回User对象
-->
<select id="findAll" resultType="com.jt.pojo.User">
select * from demo_user
</select>
</mapper>
1.2.7 Spring整合Mybatis的配置 application.yml
说明: Mybatis原生代码的结构混乱,比较复杂.所以采用Spring整合mybatis的操作.,简化开发的步骤.
#1.配置端口号 注意缩进!!!!!
server:
port: 8090
#2.配置数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
#yml文件 0不解析 如果字母以0开头则引号包裹
#password: "0123456"
password: root
#3.配置Mybatis
mybatis:
#定义别名包
type-aliases-package: com.jt.pojo
#将所有的映射文件全部加载
mapper-locations: classpath:/mappers/*.xml
#开启驼峰映射
configuration:
map-underscore-to-camel-case: true
#4.打印Sql com.jt.mapper下的Sql日志
logging:
level:
com.jt.mapper: debug
1.2.8 Spring的测试类 TestMybatis
说明: Spring为了后期测试代码方便,专门针对于测试方法,开发了一个注解@SpringBootTest
package com.jt;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest //该注解的作用启动spring容器中,之后动态的获取对象
public class TestMybatis {
@Autowired //IDEA编译异常 不影响代码的执行
private UserMapper userMapper;
@Test
public void test01(){
List<User> userList = userMapper.findAll();
System.out.println(userList);
}
}
2. Axios扩展知识
2.1 前端JS-回调地狱
说明: 如果Ajax嵌套的层级较多,则把这种结构称之为"回调地狱"
嵌套规则:
- 用户发起第一个Ajax请求.回调函数中的结果,要当做第二个ajax请求的参数.
- 用户第二个ajax回调函数的结果,要当做第三个Ajax请求的参数 以此类推!!!
回调地狱问题说明:
由于回调方法和请求的方法在2行,导致嵌套的结构没有办法优化.如果需要优化,则应该将Ajax的请求一行搞定. 例如
let result1 = axios.get(url1);
let result2 = axios.get(url2,result1)
let result3 = axios.get(url3,result2)
2.2 前端JS-回调地狱-解决方案
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Axios入门案例</title>
</head>
<body>
<!-- 1.导入js文件 -->
<script src="js/axios.js"></script>
<!-- 2.编辑JS代码 -->
<script>
/* let url1 = "http://localhost:8080/axios/findUser"
axios.get(url1)
.then(function(promise){
console.log(promise.data)
axios.get("url2",promise.data)
.then(promise2 => {
console.log(promise2.data);
axios.get("url3",promise2.data)
.then(promise3 => {
console.log(promise3.data)
//...嵌套十八层,比喻为回调地狱
})
})
}) */
/**
* 语法:
* 1.async 关键字修饰函数
* 2.await 关键字修改ajax请求
* 3.先定义函数.之后调用函数
* 语法说明: 解构赋值操作
*/
async function getUser(){
let url1 = "http://localhost:8080/axios/findUser"
let {data: result} = await axios.get(url1)
console.log(result)
//let promise= let promise = await axios.get(url1)
//console.log(promise.data)
//return promise
}
//调用函数
getUser()
/* async function getUser2(data){
let url2 = "http://localhost:8080/axios/findUser"
let promise = await axios.get(url2,data)
return promise
}
let result1 = getUser();
let result2 = getUser2(result1); */
</script>
<h1>学习Axios的ajax调用</h1>
</body>
</html>
3 Mybatis简单用法
3.1 根据ID查询数据
3.1.1 编辑测试方法
/**
* 业务需求: 根据ID查询数据
* 参数: id = 1
*/
@Test
public void test02(){
int id = 1;
User user = userMapper.findUserById(id);
System.out.println(user);
}
3.1.2 编辑Mapper接口方法
User findUserById(int id);
3.1.3 编辑映射文件
<!--根据id查询用户数据
语法: 动态获取数据 #{属性名称}
#号效果: 有预编译的效果 防止Sql注入攻击问题
所以以后取值使用#号
-->
<select id="findUserById" resultType="com.jt.pojo.User">
select * from demo_user where id= #{id}
</select>
3.2 完成用户入库操作
3.2.1 编辑测试类
/**
* 实现用户入库操作
*/
@Test
public void saveUser(){
User user = new User();
user.setName("元旦快乐").setAge(2022).setSex("女");
//如果需要返回值 则int接收
int rows = userMapper.saveUser(user);
//如果不需要返回值 则void标识
//userMapper.saveUser(user);
System.out.println("入库成功:影响:"+rows+"行");
}
3.2.2 编辑Mapper接口
int saveUser(User user);
3.2.3 编辑映射文件
<!--
规则:
1.如果接口方法中,有int类型的返回值,则入库之后,mybatis自动回传数据
2.如果接口中传递的是POJO对象.则通过#{属性}取值
大小问题:
1.windows系统中程序运行不区分大小写.
2.Linux系统 严格区分大小写.
3.程序猿口头禅: 我在我本机上没问题呀!!!!
-->
<insert id="saveUser">
insert into demo_user(id,name,age,sex) values (null,#{name},#{age},#{sex})
</insert>
3.3 完成修改和删除工作
3.3.1 编辑测试类方法
/**
* 3.修改操作 将name="元旦快乐" 改为age=17,sex=男
*/
@Test
public void updateUser(){
User user = new User();
user.setName("元旦快乐").setAge(17).setSex("男");
userMapper.updateUser(user);
System.out.println("修改操作成功!!!");
}
//4.删除操作 将name="春节快乐"的数据删除
@Test
public void deleteUser(){
String name = "春节快乐";
userMapper.deleteUser(name);
System.out.println("删除成功!!!");
}
3.3.2 编辑Mapper接口
void updateUser(User user);
void deleteUser(String name);
3.3.3 编辑Mapper映射文件
<update id="updateUser">
update demo_user set age=#{age}, sex=#{sex}
where name=#{name}
</update>
<delete id="deleteUser">
delete from demo_user where name=#{name}
</delete>
3.4 Map集合封装数据
3.4.1 编辑测试方法
/**
* 业务: 查询age> 18岁 and age <100的用户.
* 知识点:
* 1.mybatis的参数可以是基本类型或者字符串.
* 2.如果遇到多个参数,应该使用对象(POJO)进行封装.
* 3.如果通过pojo封装不方便.则使用功能最为强大的Map进行封装
* 4.Mybatis的接口方法中只允许传递单值
*/
@Test
public void testFindUserByAge(){
Map<String,Object> map = new HashMap<>();
map.put("minAge",18);
map.put("maxAge",100);
List<User> userList = userMapper.findUserByAge(map);
System.out.println(userList);
}
3.4.2 编辑Mapper接口方法
List<User> findUserByAge(Map<String, Object> map);
3.4.3 编辑Mapper映射文件
<!--
知识点1: 通过 #{参数名称/对象中的属性/Map中的key}
知识点2: xml文件中有些字符需要转义
> > < <
& &
-->
<select id="findUserByAge" resultType="com.jt.pojo.User">
select * from demo_user where age>#{minAge} and age < #{maxAge}
</select>
3.5 @Param注解 多值传参
3.5.1 需求说明
说明: 根据下列的代码,不能非常直观去了解业务. 能否优化该操作.
//Mapper层
List<User> findUserByAge(Map<String, Object> map);