SpringBoot项目:员工管理系统(基本结构)

SpringBoot_staff

写一个简单的员工管理系统,来体验 Spring Boot 开发的整个流程。

1、项目结构

  1. 创建 Spring Boot Web 项目:springboot_04_staff

  2. 导入依赖

    • 数据库JDBCMySQL 连接、Druid 数据源、MyBatis
    • 模板引擎Thymeleaf
  3. 完善包结构

    • pojo
    • dao
    • service
    • controller
    • config
    • constant
  4. 导入静态资源

    • static 目录:存放资源文件,如 CSSJS...
    • templates 目录:存放 HTML 页面

    SpringBoot项目:员工管理系统(基本结构)

2、数据库表、实体类

2.1、数据库springboot_staff

数据库表必备三字段(阿里巴巴规范)

  • id逻辑主键,无实际含义,用于唯一标识每个字段
  • create_time:创建时间
  • update_time:更新时间

部门表department

  • department_id业务主键,部门ID
  • name:部门名

SpringBoot项目:员工管理系统(基本结构)

员工表employee

部门和员工是一对多的关系

  • employee_id业务主键,员工ID
  • name:员工名
  • email
  • gender
  • birthday
  • department_id:在数据库中,用 ID 表示部门

SpringBoot项目:员工管理系统(基本结构)

2.2、实体类

  1. 不需要逻辑主键;
  2. 根据需要添加constructortoString()getter和setter,可以全部添加

部门类Department

public class Department {
    /**
     * 创建时间
     */
    private Date createTime;
    /**
     * 更新时间
     */
    private Date updateTime;
    /**
     * 部门ID
     */
    private String departmentId;
    /**
     * 部门名
     */
    private String name;

    @Override
    public String toString() {
		...
    }
}

员工类Employee

  • Department:在实体类中,用实体类表示部门
public class Employee {
    /**
     * 创建时间
     */
    private Date createTime;
    /**
     * 更新时间
     */
    private Date updateTime;
    /**
     * 员工ID
     */
    private String employeeId;
    /**
     * 员工名
     */
    private String name;
    /**
     * 邮箱
     */
    private String email;
    /**
     * 性别
     */
    private Integer gender;
    /**
     * 生日
     */
    private Date birthday;
   
    /**
     * 部门
     */
    private Department department;

    @Override
    public String toString() {
		...
    }
}

2.3、注意

  1. ORM原则

  2. 命名风格

    • 数据库:下划线
    • 实体类:小驼峰
  3. 多对一关系:员工对部门

  4. 员工实体中对部门的表示

    • 数据库- employee:部门ID——department_id
    • 实体类- Employee:部门——Department
  5. 映射问题

    • 命名风格映射;
    • department_idDepartment 的映射。

3、整合MyBatis

即整合了 MyBatis后的 DAO层10.3、整合 MyBatis

3.1、导入依赖

<!-- JDBC -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MySQL连接 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- Druid数据源 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.8</version>
</dependency>
<!-- SpringBoot整合MyBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<!-- log4j日志 -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

3.2、数据库配置文件

  • JDBC 数据库配置
  • Druid 数据源
  • MyBatis

application.yaml

spring:
  datasource:
    username: root
    password: 密码
    url: jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    # Druid数据源
    type: com.alibaba.druid.pool.DruidDataSource
    # Druid数据源配置
    initialSize: 5
    maxActive: 20
    minIdle: 5
    maxWait: 60000
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    validationQuery: SELECT 1 FROM DUAL
    testOnBorrow: false
    testOnReturn: false
    testWhileIdle: true
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    # filters:stat监控统计、log4j日志记录(需要导入log4j依赖)、wall防御sql注入
    filters: stat,wall,log4j
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
    
# 整合MyBatis配置
mybatis:
  type-aliases-package: indi.jaywee.pojo
  # Mapper.xml放在resources目录下与mapper同名的包下
  mapper-locations: classpath:indi/jaywee/mapper/*.xml
  # 自动映射:数据库下划线命名<-->实体类驼峰命名
  configuration:
    map-underscore-to-camel-case: true

3.3、Mapper

  1. Mapper 类上方添加@Mapper注解
  2. 编写基本的 CRUD,后面再根据业务需求来添加方法。

DepartmentMapper

@Mapper
public interface DepartmentMapper {
    /**
     * 根据ID查询部门
     *
     * @param departmentId 部门ID
     * @return 查询部门
     */
    Department getDepartment(String departmentId);

    /**
     * 查询所有部门
     *
     * @return 部门列表
     */
    List<Department> listDepartments();
}

EmployeeMapper

/**
 * 添加员工
 *
 * @param employee 待添加员工
 * @return 受影响行数
 */
int insertEmployee(Employee employee);

/**
 * 删除员工
 *
 * @param employeeId 员工ID
 * @return 受影响行数
 */
int deleteEmployee(String employeeId);

/**
 * 更新员工:改名
 *
 * @param employeeId 员工ID
 * @param newName    新名称
 * @return 受影响行数
 */
int updateEmployee(String employeeId, String newName);

/**
 * 根据ID查询员工
 *
 * @param employeeId 员工ID
 * @return 待查询员工
 */
Employee getEmployee(String employeeId);

/**
 * 查询所有员工
 *
 * @return 员工列表
 */
List<Employee> listEmployees();

3.4、Mapper.xml

  1. 绑定对应接口namespace="xxx"
  2. 命名映射配置下划线命名和驼峰命名的自动映射
  3. SQL 语句注意
    1. 区分命名风格:数据库字段用下划线,实体类属性用驼峰命名;
    2. 区分主键:逻辑主键id无实际含义,业务主键有业务逻辑含义;
  4. 难点Employee 的部门字段的映射

DepartmentMapper.xml

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口绑定 -->
<mapper namespace="indi.jaywee.mapper.DepartmentMapper">
    <!-- 根据ID查询部门 -->
    <select id="getDepartment" resultType="department">
        SELECT create_time,
               update_time,
               department_id,
               name
        FROM springboot_staff.department
        WHERE department_id = #{departmentId}
    </select>
    <!-- 查询所有部门 -->
    <select id="listDepartments" resultType="department">
        SELECT create_time,
               update_time,
               department_id,
               name
        FROM springboot_staff.department
    </select>
</mapper>

EmployeeMapper.xml

  1. insert:要求实体类Employee 具有 getDepartmentId 方法,否则无法获取并插入departmentId
  2. select
    1. 使用 resultMap 处理结果集映射
    2. 使用 association + 子查询,来映射部门字段(有关说明见MyBatis的多对一和一对多
<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 接口绑定 -->
<mapper namespace="indi.jaywee.mapper.EmployeeMapper">

    <!-- 添加员工 -->
    <insert id="insertEmployee">
        INSERT INTO springboot_staff.employee(create_time, update_time, employee_id, name, email, gender, birthday,department_id)
        VALUES (#{createTime}, #{updateTime}, #{employeeId},
                #{name}, #{email}, #{gender}, #{birthday}, #{departmentId})
    </insert>

    <!-- 更新员工:改名 -->
    <update id="updateEmployee">
        UPDATE springboot_staff.employee
        SET name = #{newName}
        WHERE employee_id = #{employeeId}
    </update>

    <!-- 删除员工 -->
    <delete id="deleteEmployee">
        DELETE
        FROM springboot_staff.employee
        WHERE employee_id = #{employeeId}
    </delete>

    <!-- 查询员工 -->
    <select id="getEmployee" resultMap="employeeMap">
        SELECT create_time,
               update_time,
               employee_id,
               name,
               email,
               gender,
               birthday,
               department_id
        FROM springboot_staff.employee
        WHERE employee_id = #{employeeId}
    </select>

    <!-- 查询所有员工-->
    <select id="listEmployees" resultMap="employeeMap">
        SELECT create_time,
               update_time,
               employee_id,
               name,
               email,
               gender,
               birthday,
               department_id
        FROM springboot_staff.employee
    </select>

    <!-- 结果映射:数据库department_id与实体类Department -->
    <resultMap id="employeeMap" type="employee">
        <association property="department" column="department_id" javaType="Department" select="getDepartment"/>
    </resultMap>
    <select id="getDepartment" resultType="department">
        SELECT create_time, update_time, name, department_id
        FROM springboot_staff.department
        WHERE department_id = #{department_id}
    </select>
</mapper>

4、Service层

Service层调用 DAO层方法

EmployeeService

/**
 * 添加员工
 *
 * @param employee 待添加员工
 * @return 受影响行数
 */
int insertEmployee(Employee employee);

/**
 * 删除员工
 *
 * @param employeeId 员工ID
 * @return 受影响行数
 */
int deleteEmployee(String employeeId);

/**
 * 更新员工:改名
 *
 * @param employeeId 员工ID
 * @param newName    新名称
 * @return 受影响行数
 */
int updateEmployee(String employeeId, String newName);

/**
 * 根据ID查询员工
 *
 * @param employeeId 员工ID
 * @return 待查询员工
 */
Employee getEmployee(String employeeId);

/**
 * 查询所有员工
 *
 * @return 员工列表
 */
List<Employee> listEmployees();

EmployeeServiceImpl

  • 使用@Service注解,将Service实现类注册到容器中
  • 注入EmployeeMapper
@Service
public class EmployeeServiceImpl implements EmployeeService {
    /**
     * Service层调用DAO层方法
     */
    @Resource
    EmployeeMapper employeeMapper;

    @Override
    public int insertEmployee(Employee employee) {
        return employeeMapper.insertEmployee(employee);
    }

    @Override
    public int deleteEmployee(String employeeId) {
        return employeeMapper.deleteEmployee(employeeId);
    }

    @Override
    public int updateEmployee(String employeeId, String newName) {
        return employeeMapper.updateEmployee(employeeId, newName);
    }

    @Override
    public Employee getEmployee(String employeeId) {
        return employeeMapper.getEmployee(employeeId);
    }

    @Override
    public List<Employee> listEmployees() {
        return employeeMapper.listEmployees();
    }
}

编写完 Service层后,创建相应的 ServiceTest,测试是否能正常运行

5、欢迎页面

SpringBoot 8.3、欢迎页面

  • 默认启动 Spring Boot 项目时,在没有设置首页的情况下,打开的是错误页面 Whitelabel Error Page
  • 由于使用 Thymeleaf 模板引擎,只能映射 template 目录下的页面,因此需要显式地设置欢迎页面的视图控制器

5.1、模板引擎

导入 Thymeleafstarterspring-boot-starter-thymeleaf

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  • 添加 pom 依赖后,刷新Maven

5.2、视图控制器

自定义SpringMVC

:创建自定义 SpringMVC 配置类

  • 实现WebMvcConfigurer接口的@Configuration
  • 添加视图控制器:访问//index.html,会映射到 template 目录下的index.html
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        // 欢迎页面
        registry.addViewController("/").setViewName("index");
        registry.addViewController("/index.html").setViewName("index");
    }
}
上一篇:MySQL核心技术部分基础


下一篇:Oracle 连接查询