[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);
    }

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/459842.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring boot java: 无效的目标发行版: 18

idea 搭建spring boot 报错java: 无效的目标发行版: 18 本人jdk 1.8 解决方案如下&#xff1a;

Filter实现请求日志记录

将锁有得外部访问都记录在日志文件里面&#xff0c;设计这个功能是为了&#xff08;为什么&#xff09;&#xff1a; 1. 在不引入Promentheus进行接口监控时&#xff0c;基于日志文件就可以实现整个项目得监控。 2. 当出现问题时&#xff0c;可以基于此进行流量重放。 效果如…

HNU-计算机系统-实验1-原型机vspm1.0-(二周目玩家视角)

前言 二周目玩家&#xff0c;浅试一下这次的原型机实验。总体感觉跟上一年的很相似&#xff0c;但还是有所不同。 可以比较明显地感觉到&#xff0c;这个界面越来越好看了&#xff0c;可操作与可探索的功能也越来越多了。 我们HNU的SYSTEM真的越来越好了&#xff01;&#x…

图像处理与视觉感知---期末复习重点(3)

文章目录 一、空间域和频率域二、傅里叶变换三、频率域图像增强 一、空间域和频率域 1. 空间域&#xff1a;即所说的像素域&#xff0c;在空间域的处理就是在像素级的处理&#xff0c;如在像素级的图像叠加。通过傅立叶变换后&#xff0c;得到的是图像的频谱&#xff0c;表示图…

ElasticSearch 看这一篇就够了,详解!!!

目录 核心概念 索引 映射 文档 基本操作 索引 创建 查询 删除 映射 创建 查询 文档 添加文档 查询文档 删除文档 更新文档 批量操作 高级查询 说明 语法 常见检索 查询所有[match_all] 关键词查询(term) 范围查询[range] 前缀查询[prefix] 通配符查询…

【智能算法】人工水母搜索算法(JS)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.代码实现4.参考文献 1.背景 2020年&#xff0c;Chou 等人受到水母运动行为启发&#xff0c;提出了人工水母搜索算法(Artificial Jellyfish Search Optimizer, JS)。 2.算法原理 2.1算法思想 JS模拟了水母的搜索行为&#xf…

要将镜像推送到GitLab的Registry中的步骤

1、通过cli 模式登录gitlab &#xff08;命令行模式&#xff09; docker login git.asc-dede.de Username: haiyang Password: Login Succeeded 2、查看我的本地镜像&#xff1a; 3&#xff0c;推送镜像apollo_core到对应的gitlab项目的Registry 中 docker push registry.gi…

汽车电子零部件(4):行泊一体ADAS

前言: 现阶段智能汽车行业正在大规模力推无限接近于L3的L2++或L2.9自动驾驶量产落地,类似于当初智能手机替换传统手机的行业机会期。智能汽车常见的智能驾驶功能包括: 行车场景:自适应巡航控制ACC;自动变道辅助ALC;交通拥堵辅助TJA;车道居中LCC;领航辅助NOA; 泊车场…

基于R语言的水文、水环境模型优化技术及快速率定方法与多模型教程

原文链接&#xff1a;基于R语言的水文、水环境模型优化技术及快速率定方法与多模型教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247597847&idx7&snd71869f1290d0ef9dd7fd3f74dd7ca33&chksmfa823ef0cdf5b7e655af5e773a3d3a1b200632a5981f99fe72f0…

excel同类项合并求和怎么操作?

想必很多办公人士都熟悉excel这款软件&#xff0c;那么使用过程里&#xff0c;若想合并同类项数据并求和&#xff0c;具体是如何操作的呢&#xff1f;下面就是小编带来的excel合并同类项数据并求和的操作步骤&#xff0c;很简单哦&#xff0c;看完之后你也来试试吧! 先看一下原…

反向传播 — 简单解释

一、说明 关于反向传播&#xff0c;我有一个精雕细刻的案例计划&#xff0c;但是实现了一半&#xff0c;目前没有顾得上继续充实&#xff0c;就拿论文的叙述这里先起个头&#xff0c;我后面将修改和促进此文的表述质量。 二、生物神经元 大脑是一个由大约100亿个神经元组成的复…

关于tcp协议

目录 前言&#xff1a; 一、TCP协议的基本概念&#xff1a; 二、TCP协议的主要特点&#xff1a; 2.1面向连接&#xff1a; 2.2可靠传输&#xff1a; 2.3基于字节流&#xff1a; 三、TCP连接的建立与终止&#xff1a; 3.1连接建立&#xff1a; 3.1.1SYN&#xff1a; 3…

【SystemVerilog】结构体真是太好用了~

前言 Verilog最大的缺陷之一是没有数据结构。在SystemVerilog中可以使用struct创建结构&#xff0c;struct只是把数据组织到一起&#xff0c;是数据的集合&#xff0c;所以是可综合的。 结构体是可以通过模块接口进行传递的&#xff0c;这就是本文想描述的内容。 一、结构体的…

YOLOv7改进 | 更换主干网络之PP-LCNet

前言:Hello大家好,我是小哥谈。PP-LCNet是一个由百度团队针对Intel-CPU端加速而设计的轻量高性能网络。它是一种基于MKLDNN加速策略的轻量级卷积神经网络,适用于多任务,并具有提高模型准确率的方法。与之前预测速度相近的模型相比,PP-LCNet具有更高的准确性。此外,对于计…

字符串函数(C语言详解)

1.字符串简介 字符串是一串连续的且以\0结尾的字符 char arr[]"zhangsan";//将字符串存到数组里面 char*a"lisi";//常量字符串 char arr1[]{z,h,a,n,g};//字符数组 注意&#xff1a; 1.以第一种形式初始化字符串时&#xff0c;计算机会自动在字符串末尾加…

指针(1)

1.内存和地址 1.1 内存 生活中我们有了房间号才能够快速找到房间&#xff0c;同样&#xff0c;在计算机中CPU&#xff08;中央处理器&#xff09;在处理数据时&#xff0c;需要的数据是在内存中进行读取的&#xff0c;处理完之后又会放回内存中。 在内存空间中&#xff0c…

OJ_最长公共子序列

题干 C实现 #include <iostream> #include <stdio.h> #include <algorithm> using namespace std;int dp[1002][1002];int main() {int n,m;char s1[1001];char s2[1001];scanf("%d%d",&n,&m);scanf("%s%s",s1,s2);//dp[i][j]是…

拼多多、淘宝、抖音、小红书商家,如何轻松在1688找到靠谱货源?

无论你是做拼多多、淘宝、抖音小店、小红书或者1688运营及采购商们&#xff0c;只要想在1688上寻找靠谱货源时&#xff0c;可以按照以下几个步骤进行筛选&#xff1a; 一、明确需求 首先&#xff0c;你需要清晰地了解自己的经营方向、目标消费群体以及所需产品的具体规格、材…

可变形卷积v4 |更快更强,效果远超DCNv3

专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 一、论文摘要 我们介绍了可变形卷积v4 (DCNv4)&#xff0c;这是一种高效的算子&#xff0c;专为广泛的视觉应用而设计。DCNv4通过两个关键增强解决了…

26.网络游戏逆向分析与漏洞攻防-网络通信数据包分析工具-实现生成日志文件的功能

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;25.利用全新的通…