1. 整合Mybatis-plus
1.1 基础配置
- 手动添加依赖 数据池依赖和mybatis-plus依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
- 配置文件中添加属性
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
username: root
password: root
- 添加实体类
- 编写Mapper,继承Base接口,并将泛型实例化。
@Mapper
public interface BookDao extends BaseMapper<Book> {
}
- 测试类中进行测试。
1.2 数据库表交互
- mybatis-plus对数据表进行读取时,不能读取到表的前缀,需要在配置文件中添加表前缀。
- 同时还需要添加自增属性,使数据能够实现自增功能,如 id属性。
- 开启日志属性,这样就不用采用输出语句,直接运行接口中的方法就能在控制台上直观看到数据
#配置表名前缀
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
#设置自增
id-type: auto
configuration:
#开启日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
2. 分页功能
- base接口中已经实现了分页的功能,可以直接调用方法,但是调用方法不会直接得到响应结果,需要对其进行配置。
@Test
void testGetPage(){
IPage page = new Page(1,5);
bookDao.selectPage(page,null);//返回的依旧是 Ipage接口类型是数据
}
- 添加配置类,将分页拦截器加载到mybatis-plus中。
@Configuration
public class MPConfig {
//创建mybatis-plus拦截器
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//定义拦截器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
- 分页后可以得到很多数据,如:
- 数据 当前页码 每页数据总量 最大页码 数据总量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZkMUREZw-1647693229509)(C:\Users\10990\AppData\Roaming\Typora\typora-user-images\image-20220318120655416.png)]
3. 条件查询
- 创建QueryWrapper对象,给对象添加值。
- 缺点: 需要手动添加对象的属性值
- 创建LambdaQueryWrapper 对象,可以实现自动添加对象属性值,避免错误出现。
- 针对没有输入的空值,可以在最前面添加 判断类型。
- 类似语法 if(…){}
@Test
void testGetBy(){
// QueryWrapper<Book> qw = new QueryWrapper<>();
// qw.like("type","说");
// bookDao.selectList(qw);
String name = null;
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
//lqw.like(Book::getName,"三");
lqw.like(name!=null,Book::getName,name);
bookDao.selectList(lqw);
}
}
4. 业务层快速开发
- 通过接口(Iservice)快读开发Service
- 使用通用类实现类(ServiceImpl<M,T>)快速开发ServiceImpl
- 可以在通用类的基础上做功能覆盖或功能追加
- 注意重载时不要覆盖原始操作,避免原始提供的功能丢失。
@Service
public interface IBookService extends IService<Book> {
}
@Service
public class IBookServiceImpl extends ServiceImpl<BookDao, Book> implements IBookService {
}
5. 前后端数据规范
- 后端返回的数据有的呈现Json格式输出到前端,而有的则时true false格式,对前端来说处理数据很难进行,所以需要有一套规范来使前后端数据获取时,有所关联。
- 创建Msg类,其中包括状态码,返回信息Object,以及携带的信息
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Msg {
private Boolean flag;
private Object data;
private String message;
public Msg(Boolean flag) {
this.flag = flag;
}
public Msg(Boolean flag,Object data){
this.flag = flag;
this.data = data;
}
public Msg(Boolean flag,String message){
this.flag = flag;
this.message = message;
}
}
- 此时Controller层处理数据就可以直接返回Msg,前端直接通过Msg取值
@Autowired
private IBookService service;
@GetMapping
public Msg getAll(){
return new Msg(true,service.list());
}
@PostMapping
public Msg save(@RequestBody Book book) throws IOException {
boolean flag = service.save(book);
return new Msg(flag,flag ? "添加成功^_^":"添加失败-_-!");
}
@PutMapping
public Msg update(@RequestBody Book book){
return new Msg(service.modify(book));
}
@DeleteMapping("/{id}")
public Msg delete(@PathVariable("id") Integer id){
return new Msg(service.delete(id));
}
6. Axios 发送异步请求
6.1 Vue中代码
var vue = new Vue({
el: '#app',
data:{
dataList: [],//当前页要展示的列表数据
dialogFormVisible: false,//添加表单是否可见
dialogFormVisible4Edit:false,//编辑表单是否可见
formData: {},//表单数据
rules: {//校验规则
type: [{ required: true, message: '图书类别为必填项', trigger: 'blur' }],
name: [{ required: true, message: '图书名称为必填项', trigger: 'blur' }]
},
pagination: {//分页相关模型数据
currentPage: 1,//当前页码
pageSize:5,//每页显示的记录数
total:0,//总记录数
type:"",
name:"",
description:""
}
},
- 发送异步请求
- .后面是请求方式,请求路径
- 箭头函数将得到的返回结果进行处理
- dataList 在表格中定义,并在Vue中定义, 直接将返回结果返回到 dataList 中
//列表
getAll() {
//发送异步请求
axios.get("/books").then((res)=>{
console.log(res.data);
this.dataList = res.data.data;
})
},
7. 弹框操作
- 初始Vue中定义 dialogFormVisible 为 false ,改为true 则弹出
- 调用resetForm 方法来重置表单
- resetForm 方法的实际操作就是将 formData: {},设为空。
//弹出添加窗口
handleCreate() {
//添加新增窗口
this.dialogFormVisible = true;
//重置窗口
this.resetForm();
},
8. 添加操作
- 发送post请求
- 携带this.formData 中的数据 res 为返回结果
- 具体成功的操作
- 关闭弹窗
- 弹出消息窗
- 无论处理成功与否,重新加载数据。
//添加
handleAdd () {
//发送请求
axios.post("/books",this.formData).then((res)=>{
//判断当前操作是否成功
if(res.data.flag) {
//1.关闭弹层
this.dialogFormVisible = false;
//弹消息窗
this.$message.success(res.data.message);
}else {
this.$message.error(res.data.message);
}
}).finally(()=> {
//2.重新加载数据
this.getAll();
});
},
9. 取消操作
- 关闭弹窗
- 弹消息窗
//取消
cancel(){
this.dialogFormVisible = false;
this.dialogFormVisible4Edit = false;
this.$message.info("当前操作取消");
},
10. 删除操作
- 调用$confirm函数,弹出消息框确实是否删除
- 发送异步请求,带上id
- 对返回的结果处理
- 弹消息窗
- 重新加载
// 删除
handleDelete(row) {
this.$confirm("此操永久删除信息,是否继续?","提示",{type: "info"}).then(()=>{
axios.delete("/books/"+row.id).then((res)=>{
if(res.data.flag) {
//弹消息窗
this.$message.success("删除成功");
}else {
this.$message.error("删除失败");
}
}).finally(()=> {
//2.重新加载数据
this.getAll();
});
}).catch(()=>{
this.$message.info("取消删除");
})
},
11. 修改功能
-
加载数据
-
发送异步请求获取到本行的数据
-
根据返回的数据如果有数据并且数据不为空,弹窗操作,并将数据加载到消息栏中。
-
否则表示没有数据,报错。
-
-
修改操作
- 提交表单
- 类似新增
//弹出编辑窗口
handleUpdate(row) {
axios.get("/books/"+row.id).then((res)=>{
if(res.data.flag && res.data.data!=null){
this.dialogFormVisible4Edit = true;
this.formData = res.data.data;
}else {
this.$message.error("数据同步失败,自动刷新");
}
}).finally(()=> {
//2.重新加载数据
this.getAll();
});;
},
//修改
handleEdit() {
//发送请求
axios.put("/books",this.formData).then((res)=>{
//判断当前操作是否成功
if(res.data.flag) {
//1.关闭弹层
this.dialogFormVisible4Edit = false;
//弹消息窗
this.$message.success("修改成功");
}else {
this.$message.error("修改失败");
}
}).finally(()=> {
//2.重新加载数据
this.getAll();
});
},
12. 分页操作
业务层操作:返回的是page对象,其中携带了 currentPage,pageSize,total 等数据。
@GetMapping("/{currentPage}/{pageSize}")
public Msg getPage(@PathVariable int currentPage,@PathVariable int pageSize,Book book){
IPage<Book> page = service.getPage(currentPage, pageSize,book);
//如果当前页码值大于总页码值,重新执行操作查询操作,使用最大页码值作为当前页码值
if(currentPage > page.getPages()){
page = service.getPage((int) page.getPages(), pageSize,book);
}
return new Msg(true,page);
}
- Vue中定义了分页的三个参数,分别为currentPage,pageSize,total,将当前页码,每页多少数据添加到请求中
- 将返回的结果赋值给数据
//分页查询
getAll(){
param="?type="+this.pagination.type;
param+="&name="+this.pagination.name;
param+="&description="+this.pagination.description;
axios.get("/books/"+this.pagination.currentPage+"/"
+this.pagination.pageSize+param).then((res)=>{
//console.log(res.data);
this.pagination.currentPage=res.data.data.current;
this.pagination.pagesize = res.data.data.size;
this.pagination.total=res.data.data.total;
this.dataList = res.data.data.records;
})
},
//切换页码
handleCurrentChange(currentPage) {
//修改页码值当前选中的页码值
this.pagination.currentPage = currentPage;
this.getAll();
},
13. 查询操作
-
添加到getall中, 和分页操作一起进行。
-
服务层代码
- 动态按条件查询
@Override
public IPage<Book> getPage(int currentPage, int pageSize, Book book) {
IPage<Book> page = new Page<>(currentPage,pageSize);
//动态条件查询
LambdaQueryWrapper<Book> lqw = new LambdaQueryWrapper<>();
lqw.like(Strings.isNotEmpty(book.getType()),Book::getType,book.getType());
lqw.like(Strings.isNotEmpty(book.getName()),Book::getName,book.getName());
lqw.like(Strings.isNotEmpty(book.getDescription()),Book::getDescription,book.getDescription());
return bookDao.selectPage(page,lqw);
}
- 控制层代码
@GetMapping("/{currentPage}/{pageSize}")
public Msg getPage(@PathVariable int currentPage,@PathVariable int pageSize,Book book){
IPage<Book> page = service.getPage(currentPage, pageSize,book);
//如果当前页码值大于总页码值,重新执行操作查询操作,使用最大页码值作为当前页码值
if(currentPage > page.getPages()){
page = service.getPage((int) page.getPages(), pageSize,book);
}
return new Msg(true,page);
}
- 查询按钮同样绑定 GetAll()函数。用于得到数据。