使用Navicat创建MySQL表
info表(包括id和title, id为主键且自动递增); info_content表(包括id, info_id, content, id为主键且自动递增)。info表为主表,info表中的一条数据对应info_content表中的多条数据:
Springboot编写接口
编写实体类:
编写 Info 实体类(entity):
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.List;
@TableName("user")
@Data
public class Info {
@TableId(type = IdType.AUTO)
private Integer id;
private String title;
//表示以下数据并不是在数据库中存在
@TableField(exist = false)
private List<InfoContent> contentList;
}
编写 InfoContent 实体类(entity):
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@TableName("info_content")
@Data
public class InfoContent {
@TableId(type = IdType.AUTO)
private Integer id;
private Integer info_id;
private String content;
}
Info 中的 contentList 就包含一个或多个 InfoContent 实体。
编写xml文件:
Info.xml 用于定义 SQL查询语句 及 返回结果:
<!DOCTYPE mapper PUBLIC "-//mybatis.org// DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.InfoMapper">
<resultMap id="infoMap" type="com.example.demo.entity.Info">
<result property="id" column="id"/>
<result property="title" column="title"/>
<collection property="contentList" javaType="ArrayList" ofType="com.example.demo.entity.InfoContent">
<!-- column对应查询返回的列,property对应返回的对象的属性-->
<result column="if_content" property="content"/>
</collection>
</resultMap>
<!-- SQL 查询-->
<select id="findPage" resultMap="infoMap">
SELECT info.*, info_content.content if_content from info
left join info_content on info.id = info_content.info_id
</select>
</mapper>
编写Mapper:
编写 InfoMapper (mapper),在其中定义findPage一对多查询方法(xml文件中select部分的id):
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.entity.Info;
public interface InfoMapper extends BaseMapper<Info> {
//一对多查询
Page<Info> findPage(Page<Info> page);
}
编写Controller:
编写 UserInfoController (controller)
package com.example.demo.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.Info;
import com.example.demo.mapper.InfoMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
@RequestMapping("/info") //在Vue中引用时需要声明
public class InfoController {
@Resource
InfoMapper infoMapper;
//后台分页模糊查询
@GetMapping
public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
@RequestParam(defaultValue = "10") Integer pageSize,
@RequestParam(defaultValue = "") String search){
LambdaQueryWrapper<Info> wrapper = Wrappers.<Info>lambdaQuery();
if(StringUtils.isNotBlank(search)){
wrapper.like(Info::getId,search);
}
Page<Info> infoPage = infoMapper.findPage(new Page<>(pageNum,pageSize));
return Result.success(infoPage);
}
}
在编写开以上文件之后,运行Spring boot项目,可以通过localhost:****(端口号)/xxxx(接口)查看输出结果
可以看出取出的contentList是对象数组,但是其实我们真正需要的只是由content值组成的字符串数组,虽然返回的结果不影响使用,但是还是可以进一步优化!
Vue调用接口,读取数据
<template>
<div>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>卡片名称</span>
<el-button style="float: right; padding: 3px 0" type="text" @click="dialogVisible = true">操作按钮</el-button>
</div>
<el-collapse v-model="activeNames" accordion> <!-- @change="handleChange"-->
<el-collapse-item v-for="item in items" :key="item.id" :title="item.title" :name="item.id">
<div v-for="(v,i) in item.contentList" :key="i">{{v.content}}</div>
</el-collapse-item>
</el-collapse>
</el-card>
<!--对话框-->
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"> <!--:before-close="handleClose"-->
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="submit()">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import request from '@/utils/request'
export default{
data(){
return{
dialogVisible:false,
activeNames:"1",
items:[]
}
},
methods: {
submit(){
this.dialogVisible = false;
let _id = this.items.length>0?Math.max(...this.items.map(v=>v.id))+1:1;
this.items.push({
id:_id,
title:'这是新添加的数据 == '+_id,
contentList:[
{content:'这是新添加的数据'}
]
})
},
load(){
request.get("/info",{
pageNum:1,
pageSize:10,
search:''
}).then(res=>{
console.log(res);
let {code,result,msg} = res;
if(code=="0"){
this.items = res.data.records;
this.activeNames = this.items[0].id || 1;
};
},err=>{
console.log(err)
})
}
},
mounted(){
this.load()
}
}
</script>
页面展示效果: