Day10-综合案例1

1.导入前后端项目

1.导入后端项目

【1】将课后资料中素材中的后台项目放到你的idea工作空间,然后在idea中导入后端项目

image-20220219182712974

image-20220219182916950

【2】修改你的idea的maven路径

image-20210617113756802

【3】修改tomcat和连接端口号,目的不要和前端项目端口号冲突

image-20210617114234846

2.导入前端项目

【1】找到素材\前端项目

image-20211219142238915

【2】将压缩包复制到vscode的工作目录并解压

image-20211219142348382

【3】使用vscode打开前端项目

【4】在vscode中切换到前端项目位置,并输入命令cnpm i安装前端依赖

image-20211219142924873

【5】运行前后端项目,在终端输入命令npm run dev,访问前端页面,向后端发送请求,效果如下:

image-20211219142952564

image-20210617115019151

2. 项目需求

1.模块分析

学习目标

  • 掌握用户角色权限表关系以及设计原则

内容讲解

1.我们今天完成的项目整体分为三个模块:
	用户模块  功能:增删改查
	角色模块  功能:增删改查
	权限模块  功能:增删改查
	
2.分析:
	用户和角色的关系:
		一个用户具有多个角色。举例:张三用户可以是QQ黄钻 绿钻 等
		一个角色可以对应多个用户。举例:QQ黄钻可以是张三 李四 等
		
#用户和角色属于多对多的关系,根据表设计原则,多对多关系创建中间表,在中间表中起码要有另外两张主表用户和角色的主键作为外键进行关联

	角色和权限的关系:
		一个角色可以有多种权限。举例:QQ黄钻:可以查看被挡访客,可以装扮空间等
		一种权限可以对应多个角色。举例:可以查看被挡访客的权限可以是QQ黄钻,也可以是绿钻
	
#角色和权限属于多对多的关系,根据表设计原则,多对多关系创建中间表,在中间表中起码要有另外两张主表权限和角色的主键作为外键进行关联
	
#注意:用户 角色 权限具有经典的五张表

内容小结

1.用户和角色具有多对多关系,创建中间表

2.角色和权限具有多对多关系,创建中间表

2.使用ER图描述五张表的关系

学习目标

  • 能够使用ER图描述五张表的关系

内容讲解

image-20210127085517907

内容小结

注意:

1.表之间是多对多需要创建中间表维护两张主表的关系

2.表之间是一对多关系:需要将一方的主键作为多方的外键

3.表之间是一对一关系:需要在任意一方将另一方的主键作为外键

3.创建表的sql语句

-- 1.用户表t_user
CREATE TABLE `t_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT, -- 用户编号
  `username` varchar(32) DEFAULT NULL,	-- 用户名字
  `password` varchar(32) DEFAULT NULL,	-- 用户密码
  `remark` varchar(32) DEFAULT NULL,	-- 用户备注
  `email` varchar(32) DEFAULT NULL,		-- 用户邮箱
  `createTime` timestamp not NULL DEFAULT CURRENT_TIMESTAMP, -- 该用户创建时间
  `updateTime` timestamp not NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, -- 该用户修改时间
  PRIMARY KEY (`id`) -- 设置主键
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_user
-- ----------------------------

insert into t_user values(null,'admin','202cb962ac59075b964b07152d234b70',null,'admin@163.com',null,null)
,(null,'zhansan','123',null,'zhansan@163.com',null,null);

-- 2.角色表t_role
CREATE TABLE `t_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT, -- 角色id
  `name` varchar(32) DEFAULT NULL,	-- 角色名字
  `keyword` varchar(64) DEFAULT NULL,	-- 角色关键字
  `description` varchar(128) DEFAULT NULL,	-- 角色描述
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_role
-- ----------------------------
INSERT INTO `t_role` VALUES ('1', '管理员', 'ROLE_ADMIN', '这是管理员')
,('2', '会员', 'ROLE_MEMBER', '这是会员')
,('3', '游客', 'ROLE_VISITOR', '这是游客');

-- 3.权限表
CREATE TABLE `t_permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT, -- 权限编号
  `name` varchar(32) DEFAULT NULL,		-- 权限名字
  `keyword` varchar(64) DEFAULT NULL,	-- 权限关键字
  `description` varchar(128) DEFAULT NULL,	-- 权限描述
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_permission
-- ----------------------------
INSERT INTO `t_permission` VALUES ('1', '新增', 'ITEM_ADD', '这是新增权限')
,('2', '删除', 'ITEM_DELETE', '这是删除权限')
,('3', '编辑', 'ITEM_EDIT', '这是编辑权限')
,('4', '查询', 'ITEM_QUERY', '这是查询权限');

-- 4.用户角色中间表
CREATE TABLE `t_user_role` (
  `user_id` int(11) NOT NULL, 
  `role_id` int(11) NOT NULL,
  PRIMARY KEY (`user_id`,`role_id`),
  KEY `FK_Reference_8` (`role_id`),
  CONSTRAINT `FK_Reference_7` FOREIGN KEY (`user_id`) REFERENCES `t_user` (`id`),
  CONSTRAINT `FK_Reference_8` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_user_role
-- ----------------------------
INSERT INTO `t_user_role` VALUES ('1', '1'),('2', '2');


-- 5.角色权限中间表
CREATE TABLE `t_role_permission` (
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) NOT NULL,
  PRIMARY KEY (`role_id`,`permission_id`),
  KEY `FK_Reference_12` (`permission_id`),
  CONSTRAINT `FK_Reference_11` FOREIGN KEY (`role_id`) REFERENCES `t_role` (`id`),
  CONSTRAINT `FK_Reference_12` FOREIGN KEY (`permission_id`) REFERENCES `t_permission` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of t_role_permission
-- ----------------------------
INSERT INTO `t_role_permission` 
	VALUES ('1', '1'),('1', '2'),('1', '3'),('1', '4'),('2', '3'),('2', '4'),('3', '4');

创建好表之间的关系图:

image-20210513092755560

image-20201106091731134

3.BaseServlet编写(掌握)

1.学习目标

  • 优化servlet的编写,不是每个需求对应一个servlet,而是每个模块对应一个servlet。

2.内容讲解

1.问题

举例:

​ 用户模块:创建一个用户模块的servlet:UserServlet 增删改查 addUserServlet deleteUserServlet updateUserServlet queryAllUsersServlet....

​ 角色模块:创建一个角色模块的servlet:RoleServlet 增删改查

​ 权限模块:创建一个权限模块的servlet:PermissionServlet 增删改查

按照以前做法每个需求都会存在一个servlet,那么每个模块会有大概至少四个servlet,三个模块会有至少12个servlet,那么在实际开发中模块会有很多,这样造成会有很多个servlet,如果具有相同的代码,那么每个servlet中代码会产生冗余的代码

2.解决问题

所以我们接下来会对于每个模块创建一个servlet,然后在该servlet完成该模块的增删改查操作。这样就可以减少servlet的创建。

举例:用户模块只有一个:UserServlet ,在UserServlet中定义对用户模块的增删改查方法,然后根据浏览器客户端的请求来决定执行UserServlet中的哪个方法。

3.代码如何实现

【1】在vue脚手架中书写向后台的请求url如下:

/user/find
/user/findById
/user/update
/user/add
/user/delete
说明:
	1.
		/user/find: user表示请求的模块名,即访问的哪个模块,用户模块是user,角色模块就是role,权限模块是permission
		find:在servlet中首先根据相应的api获取到find,find表示在servlet中要执行的方法名

【2】代码实现

1.创建servlet
2.在servlet中获取请求的url中的方法名
3.判断当前url的路径请求的是哪个方法
4.在servlet中创建增删改查的四个方法
5.在不同的方法体中完成代码
package com.itheima.case2.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/user/*")
public class UserServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求的方法名
        String url = request.getRequestURI();//  "/user/find"
        //获取最后一个/出现的索引
        int lastIndex = url.lastIndexOf('/');
        //从指定索引位置截取到末尾
        String methodName = url.substring(lastIndex + 1);

        //3.判断当前url的路径请求的是哪个方法
        if ("find".equals(methodName)) {
            //执行查询所有用户的方法
            find(request, response);
        } else if ("update".equals(methodName)) {
            //执行根据id更新用户的方法
            update(request, response);
        } else if ("add".equals(methodName)) {
            //执行添加用户的方法
            add(request, response);
        } else if ("delete".equals(methodName)) {
            //执行根据id删除用户的方法
            delete(request, response);
        }
    }

    //4.在servlet中创建增删改查的四个方法
    //5.在不同的方法体中完成代码
    private void delete(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("根据id删除用户");
    }

    private void add(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("添加用户");

    }

    private void update(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("根据id更新用户");
    }

    private void find(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("查询所有用户");
    }
}

3.内容小结

我们这里实现了通过一个UserServlet完成对用户模块的增删改查。只需要根据用户的请求地址来判断到底执行哪个方法:

http://localhost:8080/user/find----执行查询用户方法
http://localhost:8080/user/update----执行更新用户方法
http://localhost:8080/user/add-------执行添加用户方法
http://localhost:8080/user/delete-------执行删除用户方法

4.BaseServlet编写问题

1)通过我们上述编写,虽然实现了一个servlet完成一个模块的思想,但是如果当前模块的需求比较多,我们必须使用if语句判断到底执行哪个方法。

2)我们上述写法仅仅能够使用在用户模块,不能使用其他模块,例如:权限 角色模块。代码冗余

目标

解决上述两个问题:1)不使用过多if判断 2)减少代码重复性,不仅仅使用在用户模块。所有模块都可以使用

实现

1)this关键字(复习)

package com.itheima01;

/*
    this : 当前对象(谁调用,就是谁)
 */
public class ThisDemo {

    public static void main(String[] args) {

//        Person p = new Person();
        //com.itheima01.Person@610455d6
//        System.out.println(p);
        //this:com.itheima01.Person@610455d6
//        p.speak();
        System.out.println("----------");

        Person s = new Student();
//        this:com.itheima01.Student@610455d6
        s.speak();
    }
}

package com.itheima01;

public class Person {
	/*
		this:谁调用就表示谁。子类对象调用就代表子类对象
	*/
    public void speak(){
        System.out.println("this:" + this);
    }
}

class Student extends Person{

}

2)不使用过多if判断

【1】分析:

我们上述根据url获取方法名,然后根据方法名是否相等进行if条件的判断。
我们这里可以在当前用户模块无论有多少个需求都只需要书写一套模板代码,使用所有的当前用户模块的需求。

我们可以使用反射思想,根据获取的页面中的方法名来执行具体的方法,不用再判断了。

【2】步骤:

1.获取要执行的方法所属类的Class对象
2.使用Class对象调用Class类中的方法获取要执行的方法:
    	 Method getMethod(String name, Class<?>... parameterTypes)  
    		参数:
    			name:方法名----根据url获取的方法名
    			parameterTypes:要执行方法的参数类型 request  response
    
3.使用Method对象调用Method类中的invoke方法:
    	 Object invoke(Object obj, Object... args)  对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
    			参数:
    				obj:要执行方法的对象,例如find,这里传递find所属类的对象
                    args:要执行方法的实参。request  response

【3】代码实现

package com.itheima.case2.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

@WebServlet("/user/*")
public class User2Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.获取请求的方法名
        String url = request.getRequestURI();//  "/user/find"
        //获取最后一个/出现的索引
        int lastIndex = url.lastIndexOf('/');
        //从指定索引位置截取到末尾
        String methodName = url.substring(lastIndex + 1);

        //3.判断当前url的路径请求的是哪个方法
       /* if ("find".equals(methodName)) {
            //执行查询所有用户的方法
            find(request, response);
        } else if ("update".equals(methodName)) {
            //执行根据id更新用户的方法
            update(request, response);
        } else if ("add".equals(methodName)) {
            //执行添加用户的方法
            add(request, response);
        } else if ("delete".equals(methodName)) {
            //执行根据id删除用户的方法
            delete(request, response);
        }*/
        ////////////////////////////使用反射执行方法,简化if语句////////////////////////////////////////
        //1.获取要执行的方法所属类的Class对象
        //this表示当前类的对象
        Class clazz = this.getClass();
        /*
            2.使用Class对象调用Class类中的方法获取要执行的方法:
             Method getMethod(String name, Class<?>... parameterTypes)
                参数:
                    name:方法名----根据url的key获取value即方法名
                    parameterTypes:要执行方法的参数类型 request  response
         */
        try {
            Method m = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);

            /*
                3.使用Method对象调用Method类中的invoke方法:
                 Object invoke(Object obj, Object... args)  对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
                        参数:
                            obj:要执行方法的对象,例如findAllUsers,这里传递findAllUsers所属类的对象
                            args:要执行方法的实参。request  response
             */
            m.invoke(this,request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    //4.在servlet中创建增删改查的四个方法
    //5.在不同的方法体中完成代码
    public void delete(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("根据id删除用户");
    }

    public void add(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("添加用户");

    }

    public void update(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("根据id更新用户");
    }

    public void find(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("查询所有用户");
    }
}

小结:

1.我们这里使用反射思想取代了书写过多if的判断语句,简化代码开发

2.反射执行方法步骤:

1.获取要执行的方法所属类的Class对象
2.使用Class对象调用方法:getMethod(方法名,方法形参类型的Class对象)
3.使用获取Method对象调用Method类中的invoke(执行方法依赖的对象,执行方法的实参)

3)减少代码重复性,不仅仅使用在用户模块。所有模块都可以使用

BaseServlet:

package com.itheima.case2.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

//@WebServlet("/BaseServlet")
public class BaseServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       //1.获取请求的方法名
        String url = request.getRequestURI();//  "/user/find"
        //获取最后一个/出现的索引
        int lastIndex = url.lastIndexOf('/');
        //从指定索引位置截取到末尾
        String methodName = url.substring(lastIndex + 1);

        ////////////////////////////使用反射执行方法,简化if语句////////////////////////////////////////
        //1.获取要执行的方法所属类的Class对象
        //this表示子类的对象
        Class clazz = this.getClass();
        /*
            2.使用Class对象调用Class类中的方法获取要执行的方法:
             Method getMethod(String name, Class<?>... parameterTypes)
                参数:
                    name:方法名----根据url的key获取value即方法名
                    parameterTypes:要执行方法的参数类型 request  response
         */
        try {
            Method m = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);

            /*
                3.使用Method对象调用Method类中的invoke方法:
                 Object invoke(Object obj, Object... args)  对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
                        参数:
                            obj:要执行方法的对象,例如findAllUsers,这里传递findAllUsers所属类的对象
                            args:要执行方法的实参。request  response
             */
            m.invoke(this,request,response);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

UserServlet:

package com.itheima.case2.web;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

//用户模块
@WebServlet("/user/*")
public class User2Servlet extends BaseServlet {
    //4.在servlet中创建增删改查的四个方法
    //5.在不同的方法体中完成代码
    public void deleteUserById(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("根据id删除用户");
    }

    public void addUser(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("添加用户");

    }

    public void updateUserById(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("根据id更新用户");
    }

    public void findAllUsers(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("查询所有用户");
    }
}

小结:

1.我们将反射执行的方法代码放到父类BaseServlet中,然后使用其他模块的servlet直接继承BaseServlet即可

public class BaseServlet extends HttpServlet {}
@WebServlet("/user/*")
public class User2Servlet extends BaseServlet {
     public void find(HttpServletRequest request, HttpServletResponse response) {
        System.out.println("查询所有用户");
    }
    .....
}

url访问路径:
    http://localhost:8080/user/find

5.用户角色权限管理系统

1.用户查询

1.需求分析

1.启动前端服务器的时候默认显示的内容

image-20220219194404188

image-20220219213728157

2.点击侧边栏用户管理加载的页面

image-20201106103541936

侧边栏用户管理的代码:

App.vue

userList.vue内容:

整个页面加载的时候视图还没准备好,需要在created函数中向后台服务器发送请求获取所有的用户信息:

浏览器显示效果:

image-20201106103746869

注意:

【1】通过观察我们发现userList页面不仅仅显示用户信息,还有角色信息,所以我们要针对用户和角色表进行关联查询。

我们希望在userList.vue页面的中的视图加载之前准备好数据,我们必须在userList.vue页面中的vue生命周期函数created中向后台发送请求获取用户和角色信息。将数据准备好即可。

【2】element实现分页只需要获取后台数据和数据表总记录数即可:

image-20220219220034479

2.流程分析

image-20201106110853929

#web
1.获取页面提交的数据封装到分页的实体类中
2.创建业务层对象
3.使用业务层对象调用分页查询方法,将查询结果封装到分页结果PageResult实体类中
4.将Result对象响应给浏览器

#service
1.定义方法接收web层传递的数据
2.获取mybatis的会话对象
3.使用会话对象调用方法获取接口代理对象
4.使用接口代理对象调用接口中的分页查询方法
5.使用接口代理对象调用方法查询用户表的所有行记录数
6.将行记录数和用户数据封装到PageResult对象中
7.关闭会话对象
8.返回PageResult对象

#dao
1.在接口中定义分页查询方法
2.在接口中定义查询所有行记录数方法

3.代码实现

1.userList.vue组件中向后台请求用户和角色信息数据

 /*
            当前页面的视图准备好之前,去后台加载数据,先把数据准备好,然后执行到挂载mounted的生命周期的时候将数据挂载到视图上
  */
 created() {
     	 /*  axios.post("http://127.0.0.1:8080/userServlet").then(response => {
                console.log(response.data);
            });*/
          /*  //分页查询用户列表
            this.getUserList();
            //查询所有的角色
            //  (添加用户和修改用户的时候要展示所有角色以供选择)
            this.getRoleList();*/
          
     		  //调用vue对象中向后台获取所有用户数据的函数
            this.getUserList();
            //我们在这里调用getRoleList函数,向后台发送异步请求,请求角色信息,将角色信息放到vue中data中的 roleList: []中
            //我们在created函数中先去准备数据,然后随着vue的生命周期mounted挂载的时候就会将数据自动挂载到视图上:
            /*      <el-option

                    </el-option>
            */
            this.getRoleList();  
     
        },
 //TODO: 获取用户分页数据
            getUserList() {

                let url = "/user/find";
                
                 let param = {
                     // 当前页码
                    currentPage : this.pagination.pageNum,
                    //每页显示数据的条数
                    pageSize : this.pagination.pageSize
                }
                axios.post(url,param).then(response=>{
                    //指定总记录数
                    this.pagination.total = response.data.result.total;
                    //执行分页显示的数据
                    this.userList = response.data.result.rows;
                })
            }

小结:

我们使用axios向后台servlet发送请求,需要携带请求servlet的路径user以及执行的servlet的方法名findAllUsersByPage,由于是分页查询还必须携带当前页码和每页显示的数据条数

2.web层

package com.itheima.case2.web;


import com.itheima.case2.pojo.vo.PageResult;
import com.itheima.case2.pojo.vo.QueryPageBean;
import com.itheima.case2.pojo.vo.Result;
import com.itheima.case2.service.UserServiceImpl;
import com.itheima.case2.utils.BaseController;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/user/*")
//public class UserServlet extends HttpServlet {
public class UserServlet extends BaseServlet {
   
    private void find(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //获取请求参数
        try{
            //将页面提交的数据封装到QueryPageBean中
            QueryPageBean queryPageBean = BaseController.parseJSON2Object(request, QueryPageBean.class);

            //调用业务层的查询方法
            UserServiceImpl service = new UserServiceImpl();
            PageResult page = service.selectByPage(queryPageBean);
//            int i = 1/0;
            //响应给客户端
            BaseController.printResult(response,new Result(true,"查询成功!",page));
        } catch (Exception e) {
            e.printStackTrace();
            BaseController.printResult(response, new Result(false, "查询失败!"));
        }
    }
}

小结:

整体思路就是获取页面提交的当前页码和每页显示条数传递给业务层,返回PageResult对象。

3.service层编写

public class UserServiceImpl {
    //分页查询所有用户的角色
    public PageResult selectByPage(QueryPageBean queryPageBean) {
        //1. 参数处理
            // 以前计算数据库索引, 现在不算 TODO:
//        queryPageBean.getOffset();
        //2. 数据库查询
        SqlSession session = SqlSessionUtil.getSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> list = mapper.findUserByPage(queryPageBean);
//        Long total = mapper.findUserTotal(queryPageBean);
        Long total = mapper.findUserTotal();
        //3. 结果封装
        PageResult pageResult = new PageResult(total, list);
        session.close();
        return pageResult;
    }
}

小结:

向分页实体类PageResult中封装数据:

​ 1)分页查询的所有用户集合list

​ 2) 用户表的所有行记录数

4.dao层编写

【1】查询用户表的所有行记录数

public interface UserMapper {
   /*
      查询用户表的所有行记录数
   */
    @Select("select count(*) from t_user")
    Long findUserTotal();
}

【2】分页查询用户和角色信息

1.根据之前分析我们了解用户和角色属于多对多的关系。并且我们这里是查询用户,所以我们可以在用户表对应实体类中定义单列集合保存多个角色的信息

image-20220219223106479

2.sql语句:

1.先在t_user表中进行分页查询,假设起始索引是0,每页显示5条数据
2.将上述查询的结果作为临时表和t_role以及t_user_role表进行连接查询
-- 1.在t_user表中分页查询用户数据
select * from t_user limit 0,5;
-- 2.根据分页查询的用户数据关联角色表查询用户对应的角色信息
select u.*,r.id rid,r.name from
(select * from t_user limit 0,5) u
inner join t_user_role ur
inner join t_role r
on u.id = ur.user_id and
ur.role_id = r.id

3.创建映射文件

image-20201106140804590

加载其它的映射文件 xml形式
    包扫描方式加载mapper映射文件,说明:
    1. 要求mapper映射文件,与mapper接口要放在同一个目录
    2. 要求mapper映射文件的名称,与mapper接口的名称要一致

在maven项目中配置文件一定放到resources下面,并且还必须保证和UserMapper接口一致:

在resources目录上右键创建目录,这个目录和UserMapper接口所在的目录一致即可,这样生成的文件位置就会在同一个目录下面。

image-20201106141127847

image-20201106141227835

注意:创建文件夹这里书写:

com/itheima/case2/dao

image-20201106141404711

UserMapper.xml

<?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">
<!--
映射文件
namespace 指定接口的类全名
-->
<mapper namespace="com.itheima.case2.dao.UserMapper">
    <!--
        1.id="findAllUsersByPageMap" : 表示唯一标识,通过属性值关联下面的select标签
        2.type="user":接口中关联方法的返回值类型,是容器中的泛型类型
        3.autoMapping="true":如果实体类和数据表的字段名一致那么会自动映射
    -->
    <resultMap id="findAllUsersByPageMap" type="user" autoMapping="true">
        <!--配置t_user表和User实体类中的主键映射关系、
            4.<id column="id" property="id"/> :column表示数据表的字段名 property 表示实体类中的成员变量名
        -->
        <id column="id" property="id"/>
        <!--
            在mybatis中没有多对多,配置一对多,一个用户对应多个角色,使用的标签是collection
                5.ofType="role"表示List集合中保存的实体类类型
                6.autoMapping="true":如果实体类和数据表的字段名一致那么会自动映射
                7.property="roles":表示在User实体类集合容器对象名是roles
        -->
        <collection property="roles"  autoMapping="true" ofType="role">
            <!--
                8.配置t_role表和实体类Role之间主键的映射关系:
                    1)column="rid" 表示数据表的字段名
                    2)property="id" 表示Role实体类的成员变量名
            -->
            <id column="rid" property="id"/>
        </collection>
    </resultMap>

    <!--
    查询语句
    id: 接口中方法的名字 findAllUsersByPage
    resultMap:如果是多表查询这里使用resultMap,然后创建resultMap标签,通过resultMap的属性值findAllUsersByPageMap进行关联
    List<User> findAllUsersByPage(int startIndex, int pageSize);
    -->
    <select id="findAllUsersByPage" resultMap="findAllUsersByPageMap">
       select u.*,r.id rid,r.name from
        (select * from t_user limit #{startIndex},#{pageSize}) u
        inner join t_user_role ur
        inner join t_role r
        on u.id = ur.user_id and
        ur.role_id = r.id
    </select>
</mapper>

小结:

1.在使用mybatis的映射文件进行配置多表查询,在select标签的属性需要使用resultMap

2.在resultMap标签中配置一对多的关联使用collection标签进行配置

  <collection property="roles"  ofType="Role" autoMapping="true" >
            <!--配置角色的主键和成员变量的关系-->
            <!--
                注意:
                    1.这里必须配置以下内容,因为sql语句查询的角色id列名是rid,property="id"是Role实体类中的成员变量名,两个内容不一致了
                    必须配置
                    2.column="rid" 属性值rid是下面select标签文本中sql语句查询的角色主键的列别名
            -->
            <id column="rid" property="id"/>
     </collection>

4.UserMapper接口

public interface UserMapper {
    /*
        分页查询所有的用户信息以及用户对应的角色信息
     */

    List<User> findUserByPage(QueryPageBean bean);

}

5.userList.vue组件处理响应数据

getUserList() {       
           //分页查询用户列表
            //1.使用axios向后台发送异步请求,提交请求参数
            let params = "methodName=findAllUsersByPage&curPage=" + this.pagination.pageNum + "&pageSize=" + this.pagination.pageSize;
            axios.post("http://127.0.0.1:8080/user", params)
                .then(resp => {
                    //获取响应数据
                    let data = resp.data;
                    // console.log(data);
                    //判断是否查询成功
                    if(data.flag){
                       //指定总记录数
                       this.pagination.total = response.data.result.total;
                       //执行分页显示的数据
                       this.userList = response.data.result.rows;
                    }else{
                        this.$message.error(data.message);
                    }
                });
        }
posted @   忘了鱼尾纱的猫  阅读(71)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
  1. 1 刘哈哈与大先生 刘心&大鹏
  2. 2 我们打着光脚在风车下跑,手上的狗尾巴草摇啊摇 等一下就回家 / -艾兜
  3. 3 哎呦 毛不易
  4. 4 夜、萤火虫和你 AniFace
哎呦 - 毛不易
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

作曲 : 毛不易

作词 : 毛不易

编曲Arranger :赵兆 宋涛

刚刚下过雨潮湿的空气

刚刚下过雨潮湿的空气

熟悉的风景

收拾好行李出发去旅行

希望能遇见你

也许在路上或是在家里

某时某刻某地

莫名其妙 你打了个喷嚏

戴上太阳帽我走过海岛

浪花都带着笑

笑我慌慌张张笨手笨脚

找你都找不到

你的模样虽然我不知道

依然努力奔跑

会相遇吧 在下一个街角

我会带你住进城堡 门前开满了花花草草

暖风拂过你的裙角 蝴蝶在你身边围绕

等到月亮挂在树梢 我会轻轻把你拥抱

哎哟 好想长生不老

戴上太阳帽我走过海岛

浪花都带着笑

笑我慌慌张张笨手笨脚

找你都找不到

你的模样虽然我不知道

依然努力奔跑

会相遇吧 在下一个街角

我会带你住进城堡 门前开满了花花草草

暖风拂过你的裙角 蝴蝶在你身边围绕

等到月亮挂在树梢 我会轻轻把你拥抱

哎哟 好想长生不老

我会带你住进城堡 门前开满了花花草草

暖风拂过你的裙角 蝴蝶在你身边围绕

等到月亮挂在树梢 我会轻轻把你拥抱

哎哟 好想长生不老

我会带你回到故乡 回到出发之前的地方

你的未来我的过去 就在这里合二为一

明天刮风还是下雨 明天生活是悲是喜

哎哟 有你不费力气

哎哟 快让我遇见你

制作人Producer:李健 赵兆

制作人Producer:李健 赵兆

制作人Producer:李健 赵兆

键盘Keyboard:宋涛

吉他Guitar:劳国贤

合音Backing Vocal:梁古驰

混音Mixing:李游

母带Mastering:Joe LaPorta .(Sterling Sound. NY)

录音棚Studio:55TEC . Beijing

录音Recording:李游 李杨

人声录音Vocal Recording:李杨

人声编辑Vocal Editing:李杨

录音助理Recording Assistants:郭舒文 邢铜

音乐制作发行produced and distributed: 哇唧唧哇×智慧大狗

点击右上角即可分享
微信分享提示