人力资源后端项目_03-Mybatis-Plus之代码生成器

一、mybatisplus代码生成器集成

1、创建hrm-basic-generator模块

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VYDeiLqg-1587207062910)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330102401835.png)]

2、配置

(1)pom.xml
<dependencies>

    <!--代码生成器依赖-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-generator</artifactId>
        <version>3.3.1.tmp</version>
    </dependency>
    <!--模板引擎-->
    <dependency>
        <groupId>org.apache.velocity</groupId>
        <artifactId>velocity-engine-core</artifactId>
        <version>2.2</version>
    </dependency>
    <!--数据库驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.connector.java.version}</version>
    </dependency>

</dependencies>
(2)模板准备

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bYNS9ycg-1587207062912)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330102502138.png)]

(3)main方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zdLNeZbu-1587207062916)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330102542943.png)]

package io.niker.basic.util;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class CodeGenerator {

    //加载properties属性文件
    public static Properties properties;

    static {
        properties = new Properties();
        try {
            properties.load(CodeGenerator.class.getResourceAsStream("/mybatis-generator-system.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流资源
        }
    }

    public static void main(String[] args) {

        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = properties.getProperty("project.base.path");//获取项目路径
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor(properties.getProperty("project.author"));
        gc.setOpen(false);
        gc.setFileOverride(true);
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(properties.getProperty("jdbc.url"));
        dsc.setDriverName(properties.getProperty("jdbc.driverClassName"));
        dsc.setUsername(properties.getProperty("jdbc.username"));
        dsc.setPassword(properties.getProperty("jdbc.password"));
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent(properties.getProperty("package.parent"));//设置父包名称
        pc.setEntity("domain");
        mpg.setPackageInfo(pc);



        // 自定义配置 - 重新配置mapper.xml的生成规则
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();

        // 自定义mapper.xml生成
        String templatePath = "/templates/mapper.xml.vm";
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/" + properties.getProperty("config.mapper.location") +
                        "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        // 自定义controller的生成,使用自己的模板
        templatePath = "/templates/controller.java.vm";
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectPath + "/src/main/java/" + properties.getProperty("package.parent").replaceAll("\\.","/") +
                        "/controller/" + tableInfo.getEntityName() + "Controller" + StringPool.DOT_JAVA;
            }
        });

        String projectCommonPath = properties.getProperty("project.common.path");

        // 自定义query的生成,mybatis-generator没有query的生成策略
        templatePath = "/templates/query.java.vm";
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectCommonPath + "/src/main/java/" + properties.getProperty("package.parent").replaceAll("\\.","/") +
                        "/query/" + tableInfo.getEntityName() + "Query" + StringPool.DOT_JAVA;
            }
        });

        // 自定义domain的生成,domian应该生成到common模块
        templatePath = "/templates/entity.java.vm";
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return projectCommonPath + "/src/main/java/" + properties.getProperty("package.parent").replaceAll("\\.","/") +
                        "/domain/" + tableInfo.getEntityName() + StringPool.DOT_JAVA;
            }
        });

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);



        // 配置模板 - mybatisplus都是根据模板生成的文件,如果不想使用它的模板,可以自己设置
        //如果模板设置为null,则不会根据他的策略进行生成
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        templateConfig.setEntity(null);
        templateConfig.setController(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        //生成的表
        String tableNames = properties.getProperty("config.tables").replaceAll(" ","");
        strategy.setInclude(tableNames.split(","));
        strategy.setTablePrefix("t_");
        mpg.setStrategy(strategy);


        //设置模板引擎
        mpg.setTemplateEngine(new VelocityTemplateEngine());
        mpg.execute();
    }
}

二、生成系统管理中心业务代码

1、代码生成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YakTOnuI-1587207062921)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330102613549.png)]

#代码生成相关的配置信息保持到这个配置文件中
project.base.path=E:/ideaProjects/hrm-parent-repository/hrm-system-parent/hrm-system-service
project.author=lidong

#数据源配置
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/hrm?useUnicode=true&useSSL=false&characterEncoding=utf8
jdbc.username=root
jdbc.password=123456


#包配置
package.parent=io.niker.system
package.common=io.niker.common

#自定义配置
config.mapper.location=io/niker/system/mapper/
project.common.path=E:/ideaProjects/hrm-parent-repository/hrm-system-parent/hrm-system-common
config.tables=t_department, t_employee, t_employee_role, t_meal, t_meal_permission, t_menu, t_permission, t_role, t_role_permission, t_systemdictionary, t_systemdictionaryitem, t_tenant, t_tenant_meal, t_tenant_type

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-twG4EAWa-1587207062923)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330102641096.png)]

2、测试

(1)在common模块添加mybatisplus的依赖
<dependencies>
    <dependency>
        <groupId>io.niker</groupId>
        <artifactId>hrm-basic-util</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <!--mybatisplus的依赖
        这里只单纯添加mybatisplus的依赖,不要添加mybatisplus的starter-->
    <!--只是为了使得生成的代码注解不报错-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus</artifactId>
        <version>3.3.1.tmp</version>
    </dependency>
</dependencies>

三、搭建前端项目

1、创建前端的项目

结构如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HPf5UXot-1587207062925)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330163906851.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9SfIMO6G-1587207062928)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330163928513.png)]

3、上传前端代码到Gitee仓库

4、更改elementui版本

(1)package.json

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QH5h3gH8-1587207062930)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330164151993.png)]

(2)main.js

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BcK7VNum-1587207062932)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330164208490.png)]

(3)cnpm install

5、前端项目的更改

(1)项目的标题
(2)左侧菜单 - 路由
import Login from './views/Login.vue'
import NotFound from './views/404.vue'
import Home from './views/Home.vue'
import Table from './views/nav1/Table.vue'
import Form from './views/nav1/Form.vue'
import Page4 from './views/nav2/Page4.vue'
import Page5 from './views/nav2/Page5.vue'
import echarts from './views/charts/echarts.vue'


import Tenant from './views/system/Tenant.vue'

let routes = [
    {
        path: '/login',
        component: Login,
        name: '',
        hidden: true
    },
    {
        path: '/404',
        component: NotFound,
        name: '',
        hidden: true
    },
    {
        path: '/',
        component: Home,
        name: '',
        iconCls: 'fa fa-address-card',
        leaf: true,//只有一个节点
        children: [
            { path: '/main', component: echarts, name: '首页' }
        ]
    },
    {
        path: '/',
        component: Home,
        name: '系统中心',
        iconCls: 'el-icon-message',//图标样式class
        children: [
            { path: '/employee', component: Table, name: '用户管理' },
            { path: '/dept', component: Form, name: '部门管理' },
            { path: '/tenantType', component: Form, name: '租户类型管理' },
            { path: '/tenant', component: Tenant, name: '租户管理' },
        ]
    },
    {
        path: '/',
        component: Home,
        name: '课程中心',
        iconCls: 'fa fa-id-card-o',
        children: [
            { path: '/courseType', component: Page4, name: '课程类型' },
            { path: '/course', component: Page5, name: '课程管理' }
        ]
    },
    {
        path: '/',
        component: Home,
        name: '职位中心',
        iconCls: 'fa fa-id-card-o',
        children: [
            { path: '/jobType', component: Page4, name: '职位类型' },
            { path: '/job', component: Page5, name: '职位管理' }
        ]
    },
    {
        path: '*',
        hidden: true,
        redirect: { path: '/404' }
    }
];

export default routes;

四、前后联调 - 登录

1、编写后端接口,测试

/**
     * 登录
     * @param employee
     * @return
     */
@PostMapping("/login")
public AjaxResult login(@RequestBody Employee employee){

    Employee loginUser = employeeService.getOne(new QueryWrapper<Employee>().eq("username", employee.getUsername()));

    if(loginUser==null){
        return AjaxResult.me().setSuccess(false).setMessage("用户名不存在!");
    }
    if(!(loginUser.getPassword().equals(employee.getPassword()))){
        return AjaxResult.me().setSuccess(false).setMessage("密码错误!");
    }

    //map一时爽,维护火葬场,建议编写vo实体类,响应给前端的数据的封装的对象
    EmployeeVo employeeVo = new EmployeeVo();
    //对象属性的拷贝,Spring的工具类
    BeanUtils.copyProperties(loginUser,employeeVo);
    return AjaxResult.me().setSuccess(true).setMessage("登录成功!").setResultObj(employeeVo);
}

2、前端发送请求

(1)安装axios
cnpm install --save aixos vue-axios
(2)全局配置axios

main.js

import axios from 'axios'
import VueAxios from 'vue-axios'

//网关的地址
axios.defaults.baseURL = "http://localhost:1299/services/";

Vue.use(VueAxios, axios)
(3)使用axios发送登录请求

Login.vue

this.axios.post("/system/login",loginParams).then((rest) => {
    this.logining = false;
    let {success,message,resultObj} = rest.data;
    if(success){
        sessionStorage.setItem('user', JSON.stringify(resultObj));
        this.$router.push({ path: '/main' });
    }else{
        this.$message({
            message: message,
            type: 'error'
        });
    }
})

3、跨越问题解决

(1)什么是跨域问题

前端发送ajax请求,在跨域请求中肯定会出现跨域问题

(2)解决跨域问题

CORS

前端:浏览器自动发送两次请求,第一次发送options请求做询问,第二次发送正是请求

后端:配置跨域过滤器【原理:配置跨域响应头】

(3)跨域配置的过滤器放在zuul网关服务中

所有前端的请求都是通过zuul网关进行服务调用的,也就是说所有的前端请求都先访问网关,

我们就把跨域配置到zuul网关中

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kQqVZEWL-1587207062935)(C:\Users\solargen\AppData\Roaming\Typora\typora-user-images\image-20200330164554950.png)]

package io.niker.hrm.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //1) 允许的域,不要写*,否则cookie就无法使用了
        //浏览器认为127.0.0.1和localhost不是同一个域
        config.addAllowedOrigin("http://127.0.0.1:6001");
        config.addAllowedOrigin("http://localhost:6001");
        //2) 是否发送Cookie信息
        config.setAllowCredentials(true);
        //3) 允许的请求方式
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        // 4)允许的头信息
        config.addAllowedHeader("*");
        //2.添加映射路径,我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new
                UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        //3.返回新的CorsFilter.
        return new CorsFilter(configSource);
    }
}

五、租户的CRUD

1、生成租户表的代码

2、后端

TenantMapper.java

/**
     * 1、mapper的sql只关注高级查询,只要mapper的第一个参数是Page,那么自动分页
     * 而且分页后的数据自动封装到IPage对象中,IPage中就有total和rows了
     *
     *
     * 2、mapper接口多个参数了,如何在sql中获取到指定参数
     *      mybatis默认按照参数位置有着默认的参数名称
     *          arg0,arg1,....
     *          param1,param2,.......
     *      mybatis多个参数还支持绑定参数名,使用@Param注解
     * @param page
     * @param query
     * @return
     */
IPage<Tenant> selectByQuery(Page<?> page,@Param("query") TenantQuery query);

TenantMapper.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">
<mapper namespace="io.niker.hrm.mapper.TenantMapper">

    <!--mybatis关联映射-->
    <resultMap id="TenantMap" type="io.niker.hrm.domain.Tenant">
        <result property="employee.id" column="admin_id"/>
        <result property="employee.username" column="username"/>
        <result property="type.id" column="tenant_type"/>
        <result property="type.name" column="typename"/>
    </resultMap>

    <select id="selectByQuery" resultMap="TenantMap">
        select t.*,tt.name typename, e.username
        from t_tenant t
        left join t_tenant_type tt on t.tenant_type = tt.id
        left join t_employee e on t.admin_id = e.id
        <include refid="whereSql"/>

    </select>

    <!--高级查询的条件-->
    <sql id="whereSql">
      <where>
        <if test="query.keyword!=null and query.keyword!=''">
            and (
              companyName like concat('%',#{query.keyword},'%')
              or
              address like concat('%',#{query.keyword},'%')
            )
        </if>
        <if test="query.typeId!=null">
            and tenant_type = #{query.typeId}
        </if>
        <if test="query.state!=null">
            and t.state = #{query.state}
        </if>
      </where>
    </sql>
</mapper>

Tenant.java

package io.niker.hrm.domain;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.io.Serializable;
import java.util.Date;

/**
 * <p>
 * 
 * </p>
 *
 * @author lidong
 * @since 2020-03-30
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_tenant")
public class Tenant implements Serializable {

    private static final long serialVersionUID=1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private Long tenantType;

    @TableField("companyName")
    private String companyName;

    @TableField("companyNum")
    private String companyNum;

    @TableField("registerTime")
    private Date registerTime;

    private Integer state;

    private String address;

    private String logo;

    private Long adminId;

    /**
     * mybatis的多对一
     */
    @TableField(exist = false)
    private Employee admin;     // 租户管理员
    @TableField(exist = false)
    private TenantType type;    // 机构类型
}

TenantServiceImpl.java

/**
     * 高级查询+分页:
     *     传统方式:
     *          两条sql
     *          (1)count(*) 查询总条目数
     *          (2)limit 查询当前页的数据
     *          (3)封装pageList返回
     *     mybatis分页插件的方式:
     *          mapper接口将page作为第一个参数,则自动分页
     *          IPage<User> selectPageVo(Page<?> page, Integer state);
     * @param query
     * @return
     */
@Override
public PageList<Tenant> queryPage(TenantQuery query) {

    //mapper只写高级查询,分页交给分页插件
    IPage<Tenant> page = 
        baseMapper.selectByQuery(new Page<Tenant>(query.getPage(), query.getRows()), query);
    return new PageList<>(page.getTotal(),page.getRecords());

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值