目录
一.Vue工程
安装NodeJS与Vue-cli
Vue项目创建
启动Vue项目:点击npm脚本serve
改端口:在vue.config.js下
Vue文件组成:template+script+style
使用element
前端服务器当前使用Ngix
主要编写的文件
二.SpringBoot的Web工程
启动带有@SpringBootApplication注解的类来启动服务,这个启动类包含了包扫描,会扫描该类所在包与其子包的所有类
各类请求的接收与各类响应的发送
入门请求
简单参数
实体参数
复杂实体类参数
数组参数:数组接收与集合接收
时间参数
json参数
动态参数
响应数据转变成json
使用Result统一管理响应数据
案例:请求员工数据
直接访问
分层访问
在SpringBoot当中解耦
使用IOC第一步:给需要的方案加上@Component或者其衍生注解
步骤二:在需要创建的变量上加上@autowired注解自动装配
问题:如果有多个该类型的Bean对象,会报错(多个EmpDao)
最后的控制层:
下方自带可以查看所有Spring中的Bean的工具
三. 数据库查漏补缺
1.使用函数可以记录现在的时间
2.查询空where *** is null ,不能用等于
3.根据条件给行中的数据起别名
5.子条件为一行
6.在多表查询时可以使用表名.*代替某张表中所有的列
创建查询删除索引
四.在SpringBoot项目中使用MyBatis
配置信息:
案例一:查询所有用户
案例二:员工增删改查
一.根据id删除,#{}是预编译sql,使用$则是应对动态修改表名或列
二.拿到生成的主键值,并且将生成的主键值复制到Emp对象的id属性中
三.更新数据,在java代码中存储当前时间
四.查询数据无需使用Results配置数据库表与实体类属性的映射关系,在配置文件中配置即可,在xml文件中的foreach里面也能直接使用变量名表示传进来的变量
五.多个参数不需要注解(使用2.x的springboot且继承mybatis),不能把#{}放在引号,故此处使用concat函数
六.在xml文件中需要了解sql标签和include标签:可用与长sql的复用
一.Vue工程(VSCode)
安装NodeJS与Vue-cli
Vue-cli是Vue官方提供的一个脚手架,用于快速生成Vue的项目模板,依赖于NodeJS
1.安装Node.js,检查:node -v
2.npm set prefix "D:\NodeJS",检查:npm get prefix
3.npm config set registry https://registry.npmmirror.com
4.npm install -g @vue/cli,检查:vue --version
Vue项目创建
1.新建目录cmd:vue ui
2.详情界面选择npm
3.预设界面选择手动
4.功能界面添加router
5.配置选择2版本,liner选择第一个
启动Vue项目:点击npm脚本serve
改端口:在vue.config.js下
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({transpileDependencies: true,//修改端口devServer:{port: 7000,}
})
Vue文件组成:template+script+style
Home.Vue:
<template><div class="home"><img alt="Vue logo" src="../assets/logo.png"><HelloWorld msg="Welcome to Your Vue.js App"/></div>
</template><script>
import HelloWorld from '@/components/HelloWorld.vue'export default {name: 'HomeView',components: {HelloWorld}
}
</script>
使用element
1.安装element组件库与axios
PS D:\VS Codes\JavaWeb\VueDemo\demo1> npm install element-ui@2.15.3
PS D:\VS Codes\JavaWeb\VueDemo\demo1> npm install axios
2.修改main.js
import Vue from 'vue'
import App from './App.vue'
//导入路由信息
import router from './router'
//导入element
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';Vue.config.productionTip = false
Vue.use(ElementUI)
//在创建Vue时制定了路由
new Vue({router,render: h => h(App)
}).$mount('#app')
前端服务器当前使用Ngix
项目打包:点击build脚本,打包之后的项目放在dist文件下,把dist目录下的资源部署在服务器(html目录)下
启动Ngix之后服务器默认占用80端口号,被系统占用,改配置文件中http-server-listen的80->10000
worker_processes 1;
events {worker_connections 1024;
}
http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;server {listen 10000;server_name localhost;location / {root html;index index.html index.htm;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}
}
主要编写的文件
使用router实现资源的切换
router下的index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
/*
实现页面切换功能 前端路由:URL中的hash与组件之间的对应关系VueRouter:Vue的官方路由,路由器类,包含了路由表,根据路由请求(URL)在路由视图中动态渲染的组件(显示)router-link:请求链接组件,浏览器会请求为<a>router-view:动态视图组件,可以在任何区域展示与这个url对应的组件
*/Vue.use(VueRouter)
const routes = [//在这里配置路由信息{path: '/emp',name: 'emp',component: () => import('../views/element/empView.vue')},{path: '/dept',name: 'dept',component: () => import('../views/element/deptView.vue')},{path: '/element',name: 'element',component: () => import('../views/element/elementView.vue')},//配置根路径:防止找不到首页{path: '/',redirect: '/dept'}
]
const router = new VueRouter({routes
})
export default router
deptView:
<template><div><el-container style="height: 700px; border: 1px solid #eee"><el-header style="font-size:40px; background-color: rgb(238, 241, 246)">智能学习辅助系统</el-header><el-container><el-aside width="200px" style="border: 1px solid #eee"><el-menu :default-openeds="['1']"><el-submenu index="1"><template slot="title"><i class="el-icon-message"></i>系统信息管理</template><el-menu-item index="1-1"><!-- 访问不同路由 --><router-link to="/dept">部门管理</router-link></el-menu-item><el-menu-item index="1-2"><router-link to="/emp">员工管理</router-link></el-menu-item><el-menu-item index="1-3"><router-link to="/element">element元素</router-link></el-menu-item></el-submenu></el-menu></el-aside><el-main><!-- 表格 --><el-table :data="tableData" border><el-table-column prop="name" label="名称" width="250"></el-table-column><el-table-column prop="updatetime" label="最后操作时间" width="250"></el-table-column><el-table-column label="操作"><el-button type="primary" size="mini">编辑</el-button><el-button type="danger" size="mini">删除</el-button></el-table-column></el-table></el-main></el-container></el-container></div>
</template><script>
export default {data() {return {tableData: [{id: 1,name: "学工部",updatetime: "2010-01-01 12:00:00"}, {id: 2,name: "教研部",updatetime: "2010-01-01 12:00:00"}, {id: 3,name: "就业部",updatetime: "2010-01-01 12:00:00"}, {id: 4,name: "人事部",updatetime: "2010-01-01 12:00:00"}, {id: 5,name: "行政部",updatetime: "2010-01-01 12:00:00"}]}},methods: {}
}
</script><style></style>
template><div><!-- 按钮组件 --><el-row><el-button>默认按钮</el-button><el-button type="primary">主要按钮</el-button><el-button type="success">成功按钮</el-button><el-button type="info">信息按钮</el-button><el-button type="warning">警告按钮</el-button><el-button type="danger">危险按钮</el-button></el-row><br /><!-- 表格组件 --><el-table :data="tableData" style="width: 100%"><el-table-column prop="date" label="日期" width="180"> </el-table-column><el-table-column prop="name" label="姓名" width="180"> </el-table-column><el-table-column prop="address" label="地址"> </el-table-column></el-table><br /><!-- 分页组件 --><!-- 统计,每页规模,前一页,页面,后一页,跳转页 --><!-- 添加事件 --><el-paginationbackgroundlayout="total, sizes, prev, pager, next, jumper"@size-change="handleSizeChange"@current-change="handleCurrentChange":total="1000"></el-pagination><br /><!-- Dialog对话框+表单--><el-button type="text" @click="dialogFormVisible = true">打开嵌套表单的 Dialog</el-button><el-dialog title="收货地址" :visible.sync="dialogFormVisible"><el-form ref="form" :model="form" label-width="80px"><el-form-item label="活动名称"><el-input v-model="form.name"></el-input></el-form-item><el-form-item label="活动区域"><el-select v-model="form.region" placeholder="请选择活动区域"><el-option label="区域一" value="shanghai"></el-option><el-option label="区域二" value="beijing"></el-option></el-select></el-form-item><el-form-item label="活动时间"><el-col :span="11"><el-date-pickertype="date"placeholder="选择日期"v-model="form.date1"style="width: 100%"></el-date-picker></el-col><el-col class="line" :span="2">-</el-col><el-col :span="11"><el-time-pickerplaceholder="选择时间"v-model="form.date2"style="width: 100%"></el-time-picker></el-col></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">立即创建</el-button><el-button>取消</el-button></el-form-item></el-form></el-dialog><!-- 表单 --></div>
</template>
<script>
export default {data() {return {tableData: [{date: "2016-05-02",name: "王小虎",address: "上海市普陀区金沙江路 1518 弄",},{date: "2016-05-04",name: "王小虎",address: "上海市普陀区金沙江路 1517 弄",},],form: {name: "",region: "",date1: "",date2: "",},dialogFormVisible: false,};},methods: {handleSizeChange: function (val) {alert("每页记录数变化" + val);},handleCurrentChange: function (val) {alert("页码发生变化" + val);},onSubmit() {alert(JSON.stringify(this.form));},},
};
</script>
<style>
</style>
<template><div><el-container style="height: 500px; border: 1px solid #eee"><el-header style="font-size: 40px; background-color: rgb(238, 241, 246)">智能学习辅助系统</el-header><el-container><el-aside width="200px" style="border: 1px solid #eee"><el-menu :default-openeds="['1']"><el-submenu index="1"><template slot="title"><i class="el-icon-message"></i>系统信息管理</template><el-menu-item index="1-1"><!-- 访问不同路由 --><router-link to="/dept">部门管理</router-link></el-menu-item><el-menu-item index="1-2"><router-link to="/emp">员工管理</router-link></el-menu-item></el-submenu></el-menu></el-aside><el-main><el-form :inline="true" :model="searchForm" class="demo-form-inline"><el-form-item label="姓名"><el-input v-model="searchForm.user" placeholder="姓名"></el-input></el-form-item><el-form-item label="性别"><el-select v-model="searchForm.gender" placeholder="性别"><el-option label="男" value="1"></el-option><el-option label="女" value="2 "></el-option></el-select></el-form-item><el-form-item label="入职日期"><el-date-picker v-model="searchForm.entrydate" type="daterange" range-separator="至"start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">查询</el-button></el-form-item></el-form><el-table :data="tableData" border=""><el-table-column prop="name" label="姓名" width="180"></el-table-column><el-table-column prop="image" label="图像" width="180"><template slot-scope="scope"><img :src="scope.row.image" width="100px" height="70px"></template></el-table-column><el-table-column prop="gender" label="性别" width="140"><!-- 插槽 --><template slot-scope="scope">{{ scope.row.gender == 1 ? "男" : "女" }}</template></el-table-column><el-table-column prop="job" label="职位" width="140"></el-table-column><el-table-column prop="entrydate" label="入职日期" width="180"></el-table-column><el-table-column prop="updatetime" label="最后操作时间" width="230"></el-table-column><el-table-column label="操作"><el-button type="primary" size="mini">编辑</el-button><el-button type="danger" size="mini">删除</el-button></el-table-column> </el-table><br /><el-pagination background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"@current-change="handleCurrentChange" :total="1000"></el-pagination></el-main></el-container></el-container></div>
</template><script>
import axios from "axios";
export default {data() {return {tableData: [],searchForm: {name: "",gender: "",entrydate: [],},};},methods: {onSubmit: function () {alert("查询数据");},handleSizeChange: function (val) {alert("每页记录数变化" + val);},handleCurrentChange: function (val) {alert("页码发生变化" + val);},},mounted() {//发送异步请求获取数据axios.get("https://mock.apifox.cn/m1/3128855-0-default/emp/list").then((result) => {this.tableData = result.data.data;});},
};
</script>
<style></style>
二.SpringBoot的Web工程
Spring提供了若干个子项目,每个项目用于完成特定功能
基础底层框架就是Spring Framework(Spring核心)
SpringBoot免去了Framework配置繁琐、学习难度大的问题,简化配置,快速开发
创建springboot项目的时候使用SpringWeb,在sb里面已经集成了汤猫自动打开服务器
postman:发送网页http请求的插件,用于接口测试
启动带有@SpringBootApplication注解的类来启动服务,这个启动类包含了包扫描,会扫描该类所在包与其子包的所有类
@SpringBootApplication
public class Demo1Application {public static void main(String[] args) {SpringApplication.run(Demo1Application.class, args);}
}
各类请求的接收与各类响应的发送
接下来的代码写在RequestController里面
@RestController
public class RequestController {}
入门请求
1.浏览器访问@RequestMapping注解里的地址调用此方法 2.返回代表响应数据
@RequestMapping("/hello")public String hello(){System.out.println("Hello world");return "Hello world";}
简单参数
1.在访问路径中也能传递请求参数2.通过注解可以指定请求参数的名字,也可动态设置请求参数3.注解@RequestParam中的的参数表示是否一定需要,默认为true,可设置为false4.无论是get请求还是post请求都可以对请求参数进行处理
@RequestMapping("/simpleParam")public String simpleParam(@RequestParam(name="name",required = false) String username, int age){return username+":"+age;}
实体参数
可以把形参写成实体类对象,不需要类的全部参数,请求不变。
public class Address {private String province;private String city;public Address() {}public Address(String province, String city) {this.province = province;this.city = city;}public String getProvince() {return province;}public void setProvince(String province) {this.province = province;}public String getCity() {return city;}public void setCity(String city) {this.city = city;}public String toString() {return "Address{province = " + province + ", city = " + city + "}";}
}
public class User {private String name;private Integer age;private Address address;public User() {}public User(String name, Integer age, Address address) {this.name = name;this.age = age;this.address = address;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +", address=" + address +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public Address getAddress() {return address;}public void setAddress(Address address) {this.address = address;}
}
@RequestMapping("/pojoParam")public String pojoParam(User user){return user.toString();}
复杂实体类参数
复杂实体参数,类中内部类,请求使用【实体类属性.内部类】属性发送
@RequestMapping("/complexPojo")public String complexPojo(User user){return user.toString();}
数组参数:数组接收与集合接收
请求参数中,同key不同value参数的接收
也能用集合接收,需要加注解(因为默认封装到数组当中)
时间参数
时间需要注解格式
@RequestMapping("/timeParam")public String timeParam(@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")LocalDateTime updateTime){return updateTime.toString();}
json参数
传递json参数需要使用RequestBody注解使用实体类接收,请求需要使用post
@RequestMapping("/jsonParam")public String jsonParam(@RequestBody User user){return user.toString();}
动态参数
1.动态获取参数路径参数需要在请求mapping注解的路径中给变化的参数加上{}2.在方法中需要给参数加上@PathVariable注解3.请求路径中的参数有变化,如path/1...10
@RequestMapping("/pathParam/{id}")public String pathParam(@PathVariable Integer id){return id.toString();}
//多个路径参数@RequestMapping("/pathParam/{id}/{name}")public String pathParam2(@PathVariable Integer id,@PathVariable String name){return id+":"+name;}
接下来的代码在ResponseController里面
@RestController
public class ResponseController {}
响应数据转变成json
响应方法返回的数据,对象自动转json,需要在方法上写上对应的返回类型,前面的案例全是字符串
@RequestMapping("/getAddrList")public List<Address> getArrList(){List<Address> list= new ArrayList<>();Collections.addAll(list,new Address("广东","深圳"),new Address("湖南","长沙"));return list;}
使用Result统一管理响应数据
public class Result {//多了几个静态方法用来快速构造对象private Integer code ;//1 成功 , 0 失败private String msg;private Object data;public static Result success(Object data){return new Result(1, "success", data);}public static Result success(){return new Result(1, "success", null);}public static Result error(String msg){return new Result(0, msg, null);}public Result() {}public Result(Integer code, String msg, Object data) {this.code = code;this.msg = msg;this.data = data;}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}@Overridepublic String toString() {return "Result{" +"code=" + code +", msg='" + msg + '\'' +", data=" + data +'}';}
}
@RequestMapping("/getResult")public Result getResult(){return Result.error("哎哟你干嘛");}
案例:请求员工数据
1.引入dom4j依赖<dependency><groupId>org.dom4j</groupId><artifactId>dom4j</artifactId><version>2.1.4</version></dependency>
2.创建Emp实体类public class Emp {private String name;private Integer age;private String image;private String gender;private String job;public Emp() {}public Emp(String name, Integer age, String image, String gender, String job) {this.name = name;this.age = age;this.image = image;this.gender = gender;this.job = job;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getImage() {return image;}public void setImage(String image) {this.image = image;}public String getGender() {return gender;}public void setGender(String gender) {this.gender = gender;}public String getJob() {return job;}public void setJob(String job) {this.job = job;}@Overridepublic String toString() {return "Emp{" +"name='" + name + '\'' +", age=" + age +", image='" + image + '\'' +", gender='" + gender + '\'' +", job='" + job + '\'' +'}';} }
3.引入xml文件<?xml version="1.0" encoding="UTF-8" ?> <emps><emp><name>金毛狮王</name><age>55</age><image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/1.jpg</image><gender>1</gender><job>1</job></emp><emp><name>白眉鹰王</name><age>65</age><image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/2.jpg</image><gender>1</gender><job>1</job></emp><emp><name>青翼蝠王</name><age>45</age><image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/3.jpg</image><gender>1</gender><job>2</job></emp><emp><name>紫衫龙王</name><age>38</age><image>https://web-framework.oss-cn-hangzhou.aliyuncs.com/web/4.jpg</image><gender>2</gender><job>3</job></emp> </emps>
4.引入工具类(这个使用到了反射)public class XmlParserUtils {public static <T> List<T> parse(String file , Class<T> targetClass) {ArrayList<T> list = new ArrayList<T>();try {for (Element element : new SAXReader().read(new File(file)).getRootElement().elements("emp")) {Constructor<T> constructor = targetClass.getDeclaredConstructor(String.class, Integer.class, String.class, String.class, String.class);constructor.setAccessible(true);T object = constructor.newInstance(element.element("name").getText(), Integer.parseInt(element.element("age").getText()), element.element("image").getText(), element.element("gender").getText(), element.element("job").getText());list.add(object);}} catch (Exception e) {e.printStackTrace();}return list;}}
直接访问
//请求路径和html页面中的路径一样,写好访问路径@RequestMapping("/listEmp")public Result getEmp(){//获取的打包后的classes目录下的文件String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();List<Emp> empList = XmlParserUtils.parse(file, Emp.class);empList.forEach(emp -> {if ("1".equals(emp.getGender()))emp.setGender("男");else emp.setGender("女");});return Result.success(empList);}
分层访问
web当中的三层架构
controller控制层:接受请求,数据处理,响应数据
service:业务逻辑处理
dao数据访问层(data Access Object):数据库增删改查
对于DAO与Service需要编写接口(方便修改 )
DAO层:
public interface EmpDao {List<Emp> listEmp();
}
public class EmpDaoA implements EmpDao {@Overridepublic List<Emp> listEmp() {String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();return XmlParserUtils.parse(file, Emp.class);}
}
Service 层:
public interface EmpService {List<Emp> listEmp();
}
public class EmpServiceA implements EmpService {//面向接口编程,写在类最前方便多次调用private EmpDao empDao = new EmpDaoA();@Overridepublic List<Emp> listEmp() {List<Emp> empList = empDao.listEmp();empList.forEach(emp -> {if ("1".equals(emp.getGender()))emp.setGender("男");else emp.setGender("女");});return empList;}
}
@RequestMapping("/listEmp1")public Result getEmp1(){return Result.success(empService.listEmp());}
在SpringBoot当中解耦
高内聚:如在员工服务层里只处理员工这个类的信息,不会处理其他类
低耦合:在服务层中只用到了dao层的对象,尽量少调用别的对象,最佳的方案是解除耦合
在之前的方案中,服务层在调用dao层时使用到了dao层的实现类
使用不同的调用数据方法要改变服务层中的代码,解耦方案如下:
创建一个容器,把需要用到的实现类放进去,无需使用的搁置即可,这就需要spring中几个重要的概念
控制反转:Inversion of Control IOC:对象创建的控制权由程序转移到程序外部的容器,也就是说不需要您去亲自创建类的对象了
依赖注入:Dependency Injection DI:容器提供对象给某个变量 ,SpringBoot帮您做好,想要用就帮您送过来
Bean对象:IOC容器中管理的对象:也就是SpringBoot帮您管理的类
声明Bean的基础注解:@Component
由Component衍生出的三个注解(推荐使用)
Dao层:@Repository
Service层:@Service
Controller层:@Controller
@RestController:@Controller+@ResponseBody(方法返回值转变JSON返回)
使用IOC第一步:给需要的方案加上@Component或者其衍生注解
@Repository
public class EmpDaoB implements EmpDao {@Overridepublic List<Emp> listEmp() {String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();return XmlParserUtils.parse(file, Emp.class);}
}
步骤二:在需要创建的变量上加上@autowired注解自动装配
@Service
public class EmpServiceB implements EmpService {@Autowiredprivate EmpDao empDao;@Overridepublic List<Emp> listEmp() {List<Emp> empList = empDao.listEmp();empList.forEach(emp -> {if ("1".equals(emp.getGender()))emp.setGender("男");else emp.setGender("女");});return empList;}
}
问题:如果有多个该类型的Bean对象,会报错(多个EmpDao)
解决方法一:在EmpDao的实现类加Primary注解来声明需要优先使用哪一个实现类//指定老大实现类 @Primary @Repository public class EmpDaoC implements EmpDao {@Overridepublic List<Emp> listEmp() {System.out.println("EmpDaoC");String file = this.getClass().getClassLoader().getResource("emp.xml").getFile();return XmlParserUtils.parse(file, Emp.class);} }
解决方法二:在自动装配注解前加Qualifier注解指定需要使用的实现类,注意类名要小写(没有指定Bean的名字的话)@Qualifier("empDaoC")
解决方法三:使用Resource注解:相当于qualifier+autowired,需要直接指定名称@Resource(name = "empDaoC")
最后的控制层:
@RestController
public class IOCController {@AutowiredEmpService empService;@RequestMapping("/listEmp2")public Result getEmp2(){return Result.success(empService.listEmp());}
}
下方自带可以查看所有Spring中的Bean的工具
三. 数据库查漏补缺
1.使用函数可以记录现在的时间
insert into tb_user (username,name,gender,create_time,update_time)values('zhangsan','张三',23,now(),now());
2.查询空where *** is null ,不能用等于
3.根据条件给行中的数据起别名
select if(gender=1,'男性员工','女性员工') 性别,count(*) from tb_emp group by gender;
4.select case job
when 1 then '班主任'
when 2 then '讲师'
when 3 then '学工主管'
when 4 then '教研主管'
else '未分配职位'
end '职位' ,count(*)
from tb_emp group by job;
5.子条件为一行
select * from tb_emp where(entrydate,job)=('2007-01-01',2)
select * from tb_emp where(entrydate,job)
=(select entrydate,job from tb_emp wherename='韦一笑')
6.在多表查询时可以使用表名.*代替某张表中所有的列
创建查询删除索引
索引用来提高查询效率,在底层给列创建新的数据结构
主键,唯一约束会默认创建索引
create index idx_name on tb_dept(name)
show index from tb_dept
drop index idx_name on tb_dept
B+树:多路平衡搜索树,子树可以有多个
所有的数据都在叶子节点(方便查询稳定)
叶子节点之间形成双向链表方便排序
四.在SpringBoot项目中使用MyBatis
在创建项目的时候也能集成mybatis,mysqlDriver,lombok
配置信息:
主要内容为配置数据库数据,mybatis输出日志,给表名与类属性做映射
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/db1
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456
#配置mybatis的日志信息,指定输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#开启myBatis驼峰命名自动映射开关,不需要映射注解,也不需要写xml配置文件
mybatis.configuration.map-underscore-to-camel-case=true
案例一:查询所有用户
在mapper接口上注解
@Mapper//在运行时自动生成实现类对象(动态代理对象),并且将该对象文件交给IOC容器处理
public interface UserMapper {@Select("select * from user")List<User> selectAll();
}
使用lombok快速构造实体类
@Data//生成getter/setter+toString+EqualsAndHashCode方法
@NoArgsConstructor//生成无参构造方法
@AllArgsConstructor//生成全参构造
public class User {private Integer id;private String name;private Integer age;private Integer gender;private String phone;
}
在测试类中:
@Autowiredprivate UserMapper userMapper;@Testvoid test() {System.out.println(userMapper.selectAll());}
案例二:员工增删改查
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {private Integer id;private String username;private String password;private String name;private Short gender;private String image;private Short job;private LocalDate entrydate;private Integer deptId;private LocalDateTime createTime;private LocalDateTime updateTime;public Emp(String username, String name, Short gender, String image, Short job, LocalDate entrydate, Integer deptId, LocalDateTime createTime, LocalDateTime updateTime) {this.username = username;this.name = name;this.gender = gender;this.image = image;this.job = job;this.entrydate = entrydate;this.deptId = deptId;this.createTime = createTime;this.updateTime = updateTime;}
}
在下列的mapper中:
@Mapper
public interface EmpMapper {
}
一.根据id删除,#{}是预编译sql,使用$则是应对动态修改表名或列名
@Delete("delete from emp where id = #{id} ")public int deleteById(Integer id);
@Testvoid delete(){System.out.println(empMapper.deleteById(19));}
二.拿到生成的主键值,并且将生成的主键值复制到Emp对象的id属性中
@Options(useGeneratedKeys = true,keyProperty = "id")@Insert("INSERT into emp(username, name, gender, image, job, entrydate, dept_id, create_time, update_time) VALUES " +"(#{username},#{name},#{gender},#{image},#{job},#{entrydate},#{deptId},#{createTime},#{updateTime})")public void insert(Emp emp);
@Testvoid insert(){Emp emp = new Emp("zhangsan1","张三1", (short) 1,"1.jpg", (short) 1,LocalDate.of(2024,3,10),1,LocalDateTime.now(), LocalDateTime.now());empMapper.insert(emp);System.out.println(emp.getId());}
三.更新数据,在java代码中存储当前时间
@Update("Update emp set username=#{username},name=#{name},gender=#{gender},image=#{image},job=#{job},entrydate=#{entrydate},dept_id=#{deptId},update_time=#{updateTime} where id =#{id};")public void update(Emp emp);
@Testvoid update(){Emp emp = new Emp(21,"zhangsan2","123456","张三2", (short) 1,"1.jpg", (short) 1,LocalDate.of(2024,3,10),1,LocalDateTime.now(), LocalDateTime.now());empMapper.update(emp);}
四.查询数据无需使用Results配置数据库表与实体类属性的映射关系,在配置文件中配置即可,在xml文件中的foreach里面也能直接使用变量名表示传进来的变量
@Select("Select * from emp where id = #{id}")public Emp selectById(Integer id);
@Testvoid selectById(){Emp emp = empMapper.selectById(1);System.out.println(emp);}
五.多个参数不需要注解(使用2.x的springboot且继承mybatis),不能把#{}放在引号,故此处使用concat函数
@Select("select * from emp where name like concat('%',#{name},'%') and gender = #{gender} and " +"entrydate between #{begin} and #{end} order by update_time desc")public List<Emp> selectByMany(String name, Short gender, LocalDate begin, LocalDate end);
@Testvoid selectByMany(){List<Emp> emps = empMapper.selectByMany("张", (short) 1,LocalDate.of(2010, 1, 1),LocalDate.of(2030, 1, 1));System.out.println(emps);}
六.在xml文件中需要了解sql标签和include标签:可用与长sql的复用
public List<Emp> selectByCondition(String name, Short gender, LocalDate begin, LocalDate end);
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.example.springbootdemo2.mapper.EmpMapper"><sql id="commonSelect">select id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_timefrom emp</sql><select id="selectByCondition" resultType="org.example.springbootdemo2.pojo.Emp"><include refid="commonSelect"/><where><if test="name!=null and name!=''">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></select>
</mapper>
@Testvoid selectByCondition(){List<Emp> emps = empMapper.selectByCondition("张", (short) 1,LocalDate.of(2010, 1, 1),LocalDate.of(2030, 1, 1));System.out.println(emps);}