- MyBatis框架是目前最流行的数据持久层框架,使用MyBatis框架后,框架可以帮助我们自动生成JDBC相关代码,来提高开发效率,程序员只需要通过注解或者配置xml配置文件的方式来提供好需要执行的SQL语句,框架会自动根据SQL语句以及一些相关指令生成对应的JDBC代码
- MyBatis框架属于ORM框架, Object Relational Mapping 对象关系映射, 指Java对象和数据库中表的关系, Mybatis框架就是通过两者之间的关系生成的JDBC代码, 使用Mybatis框架需要定义好Mapper映射接口, 在接口中定义两者之间的关系.
- MyBatis的最大特点是:动态SQL
- 怎样创建一个带有MyBatis框架的项目:
- 点击左上角的File,New一个新的Project项目。
- 点击Spring initializr,最上面的Server URL:start.aliyun.com(start.spring.io也可,但国内网络不好,在下载spring配置文件时速度很慢,因此改为阿里云服务器提供),修改项目名Name,可修改组名Group,测试环境为Java8,因此Java选8,配置完成后,点击Next。
- 找到SpringWeb,MyBatis Framework和MySQL Driver为这个项目添加这三项依赖后,点击Finish,完成项目的创建。
- 找到application.properties,在这里面配置连接,输入数据库的连接地址,以及数据库用户名和密码.
-
MyBatis框架工作原理:使用Mybatis框架需要创建一个Mapper接口,此Mapper接口的作用是配置Java对象和数据库表的对应关系, Mybatis框架会根据此对应关系生成JDBC代码, 在Controller类中使用@Autowired注解时, Spring框架和MyBatis框架结合根据Mapper接口创建出一个实现类,并且实例化了该实现类, 然后mapper则可以直接使用,因为在实现类中已经实例化的接口中的抽象方法, 而实例化的抽象方法中就是JDBC代码.
注解
1.@Mapper和@Insert
import cn.tedu.boot04.entity.Product;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
//Mapper注解作用:设置当前接口为映射接口,映射接口是供Mybatis框架生成JDBC
//代码的依据,在接口中定义方法书写SQL语句
@Mapper
public interface ProductMapper {
//Insert注解作插入数据操作,#{xxx}此指令会从注解下面方法的参数列表中找同名列表,如果找不到
//则会调用参数列表中变量的同名get方法,会找参数列表对象中的同名属性
@Insert("INSERT INTO product VALUES(null,#{title},#{price},#{num})")
void insert(Product product);
}
2.@Select
import cn.tedu.boot04.entity.Product;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
//Mapper注解作用:设置当前接口为映射接口,映射接口是供Mybatis框架生成JDBC
//代码的依据,在接口中定义方法书写SQL语句
@Mapper
public interface ProductMapper {
//#{xxx}此指令会从注解下面方法的参数列表中找同名列表,如果找不到
//则会调用参数列表中变量的同名get方法,会找参数列表对象中的同名属性
@Insert("INSERT INTO product VALUES(null,#{title},#{price},#{num})")
void insert(Product product);
//声明返回值类型为List集合 Mybatis框架生成JDBC代码时会自动将查询到的数据
//封装到Product对象里面,并且把对象添加到一个list集合中,把集合return出来
@Select("SELECT id,title,price,num FROM product")
List<Product> select();
}
3.@Delete和@Update
import cn.tedu.boot04.entity.Product;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
//Mapper注解作用:设置当前接口为映射接口,映射接口是供Mybatis框架生成JDBC
//代码的依据,在接口中定义方法书写SQL语句
@Mapper
public interface ProductMapper {
//#{xxx}此指令会从注解下面方法的参数列表中找同名列表,如果找不到
//则会调用参数列表中变量的同名get方法,会找参数列表对象中的同名属性
@Insert("INSERT INTO product VALUES(null,#{title},#{price},#{num})")
void insert(Product product);
//声明返回值类型为List集合 Mybatis框架生成JDBC代码时会自动将查询到的数据
//封装到Product对象里面,并且把对象添加到一个list集合中,把集合return出来
@Select("SELECT id,title,price,num FROM product")
List<Product> select();
//删除注解 定义删除相关的SQL语句
@Delete("DELETE FROM product WHERE id=#{id}")
void deleteById(int id);
//修改注解 定义修改相关的SQL语句
@Update("UPDATE product SET title=#{title},price=#{price},num=#{num} WHERE id=#{id}")
void update(Product product);
}
4.@Autowired
Autowired自动装配注解,此注解是Spring框架中提供的注解 此注解添加后是Spring框架和MyBatis框架结合到一起,创建了一个 接口的实现类,并且实例化了该实现类 并赋值给了mapper变量 实现类中实现了接口里面的抽象方法(insert) (注:若mapper有报错可以加上@Autowired(required=false) required=false告诉idea这个mapper不是必须的)
package cn.tedu.boot04.controller;
import cn.tedu.boot04.entity.Product;
import cn.tedu.boot04.mapper.ProductMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
public class ProductController {
//Autowired自动装配注解,此注解是Spring框架中提供的注解
//此注解添加后是Spring框架和MyBatis框架结合到一起,创建了一个
//接口的实现类,并且实例化了该实现类 并赋值给了mapper变量
//实现类中实现了接口里面的抽象方法(insert)
//若mapper有报错可以加上@Autowired(required=false)
//required=false告诉idea这个mapper不是必须的
@Autowired
ProductMapper mapper;
@RequestMapping("/insert")
@ResponseBody
public String insert(Product p){
System.out.println("p = " + p);
mapper.insert(p);
return "添加完成!<a href='/'>返回首页</a>";
}
@RequestMapping("/select")
@ResponseBody
public String select(){
List<Product> list = mapper.select();
//把集合中的数据装进table表格中
String html = "<table border='1'>";
html+="<caption>商品列表</caption>";
html+="<tr><th>id</th><th>标题</th><th>价格</th><th>库存</th><th>操作</th></tr>";
//遍历集合 添加tr和td
for (Product p:
list) {
html+="<tr>";
html+="<td>"+p.getId()+"</td>";
html+="<td>"+p.getTitle()+"</td>";
html+="<td>"+p.getPrice()+"</td>";
html+="<td>"+p.getNum()+"</td>";
//添加删除超链接的一列,请求地址为/delete?id=xxx ?是请求地址和参数
html+="<td><a href='/delete?id="+p.getId()+"'>删除</a></td>";
html+="</tr>";
}
html+="</table>";
return html;
}
@RequestMapping("/delete")
@ResponseBody
public String delete(int id){
mapper.deleteById(id);
return "删除完成!<a href='/select'>返回商品列表</a>";
}
@RequestMapping("/update")
@ResponseBody
public String update(Product p){
mapper.update(p);
return "修改完成!<a href='/select'>返回商品列表</a>";
}
}
5.@RestController
该注解修饰Controller类时,该类的所有方法可以省去@ResponseBody注解.
同步请求和异步请求
- 同步:指单线程依次做几件事,按照顺序办事.
- 异步:指多线程同时做几件事,各个线程互不干涉,各干各的.
- 同步请求:指客户端只有一个主线程,主线程负责页面渲染和监听操作,如果需要发请求时,主线程会停止渲染页面(清空页面内容)只负责发请求,当服务器响应的数据之后,主线程再次恢复渲染工作.页面只能实现整体的改变(刷新),不能在原有页面的基础上做出改变,无法实现页面的局部改变(局部刷新).(即同步请求是因为什么事都是主线程干的,主线程只能按顺序干,分身乏术)
- 异步请求:指主线程只负责渲染页面和监听操作,由子线程负责发请求获取数据.获取到数据后可以将数据展示在原页面的基础之上,这种就称为页面的局部刷新,只有通过异步请求才能实现页面的局部刷新.(即异步请求是可以有多个线程,同时干好几件事,主线程只需要负责渲染和监听即可).
客户端如何发出异常请求
- 客户端发出请求的方式包括:
- 浏览器地址输入地址 回车后发出请求 同步请求
- 超链接发出请求 同步请求
- form表单发出请求 同步请求
- 通过前端axios框架发出异步请求
- Axios是一个js框架文件,在html页面中引入此文件即可使用.
https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js
GET和POST
- GET:请求参数在请求地址的后面且可见,由于参数可见,在传递一些敏感参数时不能使用GET请求,例如密码,请求参数大小有限制,只能传递几K的数据.GET请求可以用于存储、缓存、分享,另外GET请求比POST更快,直接响应200状态码
应用场景:一般查询请求都是用get,删除使用GET(因为删除数据时传递的参数一般都只传递一个id) - POST:请求参数在请求体里面不可见,参数大小无限制,POST请求不能用于存储、缓存、分享,且比GET请求要慢一些,因为POST需要服务器回复100,然后才会响应200状态码
应用场景:有敏感信息的请求,上传请求(因为上传文件一般比较大),一般传递参数较多时使用.
异步测试
异步测试前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>异步请求测试</h1>
<div>
{{info}}
<input type="button" value="异步get请求" @click="f1()">
<input type="button" value="异步post请求" @click="f2()">
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js "></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
<script>
let v = new Vue({
el: "body>div",
data: {
info: "异步测试"
},
methods: {
f1() {
//发出异步get请求 response代表响应对象,里面装着服务器响应的数据
axios.get("/helloGet?info=abc&age=18").then(function (response) {
//response.data代表服务器响应的数据
//alert(response.data);
//把服务器响应的数据给到变量info
v.info = response.data;
})
},
f2() {
//传递多个参数 需要将多个参数封装到一个自定义对象中
let p = {title:"手机",price:5200,num:40};
//发出异步post请求 传递参数时,只需要传入一个对象即可
axios.post("/helloPost",p).then(function (response) {
alert(response.data);
})
}
}
})
</script>
</body>
</html>
异步测试后端Controller
import cn.tedu.boot06.entity.Product;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AxiosController {
@RequestMapping("/helloAxios")
public String helloAxios() {
return "测试成功!";
}
@RequestMapping("/helloGet")
public String helloAxios(String info,int age) {
return "测试成功!info="+info+",age="+age;
}
//如果客户端发出异步post请求并且提交的是自定义对象
//同时必须要实例化一个实体类
//接收参数时必须添加@RequestBody注解
@RequestMapping("/helloPost")
public String helloAxios(@RequestBody Product product) {
System.out.println("product = " + product);
return product.toString();
}
}