[JavaWeb学习日记]Vue工程,springboot工程整合Mybatis,数据库索引

目录

一.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-pagination
      background
      layout="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-picker
              type="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-picker
              placeholder="选择时间"
              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,可设置为false
    4.无论是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;
    }
    @Override
    public 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;
    }

    @Override
    public 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;
    }

    @Override
    public 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 {
    @Override
    public 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();
    @Override
    public 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 {
    @Override
    public 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 {
    @Autowired
    private EmpDao empDao;
    @Override
    public 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 {
    @Override
    public 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 {
    @Autowired
    EmpService 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;
}

在测试类中:

    @Autowired
    private UserMapper userMapper;
    @Test
    void 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);
    @Test
    void 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);
    @Test
    void 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);
    @Test
    void 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);
    @Test
    void 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);
    @Test
    void 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 mapper
        PUBLIC "-//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_time
        from 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>
    @Test
    void selectByCondition(){
        List<Emp> emps = empMapper.selectByCondition("张", (short) 1,
                        LocalDate.of(2010, 1, 1),
                        LocalDate.of(2030, 1, 1));
        System.out.println(emps);
    }

 

  • 22
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值