任务
第一个任务,使用springboot、mysql完成获取部门、职工的人员查询和统计。
最后需要实现的效果是:
1、可以查询有多少个部门、每个部门下面多少个员工。
2、根据部门的名称查询部门下所有员工信息,包括员工的姓名、年龄、性别。支持模糊搜索
3、根据员工的姓名查询该员工的信息。支持模糊搜索。
前言
- 首先我是一名自动化学生,Java于我而言是熟悉而又陌生。熟悉在在b站看过一些视频,陌生在非科班很多东西只是听过而从未用过。
- 这是我实习的第一个任务,给了我一星期时间,算是真正动手去做一个变成项目。之前也敲过代码但是更多的是类似于力扣这类解决一个小算法问题的。工程类的事情很少有接触,在现阶段理解这也是我入门Java开发的第一个项目。
- 接下来,开始了。
工具
说实话,我认为这是对于小白而言的第一座大山,至少我多次倒在这里,在此本人仅讲述大体流程。
- JDK8(OpenJDK1.8)之所以选择用这个是因为公司使用这个(如果自己学我倾向于更新一点的)。
- IDEA 这款Java开发神器Java开发的不二之选,自行获取…即可+maven
- mysql serve 8 + mysql workbench(可视化工具) 设置好数据库服务器用户名密码。
创建项目
服务器URL换成阿里的,下载速度++。项目存放位置自己创建一个文件夹即可,名称和包名第一次可以直接用默认的demo。其余照选即可。
关于初始依赖添加,我是暂时添加了这些,他们具体功能如下
SpringBoot DevTools 用于热部署,具体在此阶段我还尚不能说清楚,先略过了。
Spring Web :搞不清加一。
MySQL Driver:mysql的驱动
MyBatis Framework:mybatis框架,封装了JDBC,简化了对数据库的操作。(相比其他框架仍算是比较麻烦的)
创建!SpringBoot,启动!
就初始的文件架构解读一下:
.idea,用不到。第一次建项目应该还有个.mvn,mmnw什么的,也用不到。
src:源文件,所有的Java代码都在此文件下的Java文件夹中编写。DemoApplication是整个项目启动入口。
resources:放置项目所需的一些资源。如静态html以及重点application.properties(用于手动配置一些东西,如数据源,mybatis,端口等)
下面的我们能用到的就只有pom.xm,这是maven用来管理依赖包的,如果需要那个依赖,去仓库复制下来链接copy进去即可。
开始做项目
-
对application.propeties进行配置。
由此可以看到中文是乱码的原因是springboot默认是UTF-8编码,我们需要更改解码方式。
文件->设置->编辑器or File ->setting->editor->encoding… 如果没有乱码,请忽略。# 应用服务 WEB 访问端口 server.port=8080 #下面这些内容是为了让MyBatis映射 #指定Mybatis的Mapper文件 (此处踩过坑,我建的文件是mapper,建议把mappers改掉,或者直接后面新建mappers) mybatis.mapper-locations=classpath:mappers/*xml #指定Mybatis的实体目录 (此处我是把mybatis这一层的包删除了,不删除后面就要多建一层) mybatis.type-aliases-package=com.example.demo.mybatis.entity
配置数据源,在application.propeties文件中复制以下内容(注意注释更改为自己的内容)
# DataSourceProperties spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver #驱动 spring.datasource.url=jdbc:mysql://localhost:3306/work2?characterEncoding=utf-8&useSSL=false&serverTimezone=Hongkong #这里的work2是我的数据库名 spring.datasource.username=root #数据库用户名 spring.datasource.password=yourpassword #数据库密码 spring.datasource.type=com.zaxxer.hikari.HikariDataSource #连接池,不太懂 spring.datasource.hikari.maximum-pool-size=15 #以下配置暂时可以忽略 spring.datasource.hikari.minimum-idle=5 spring.datasource.hikari.idle-timeout=30000 logging.level.com.cxample.demo=debug #控制台日志显示等级 spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER #这个在后面使用Swagger插件时会用到,此阶段用不到
-
设计数据库,Sql还没学(痛哭),因此在此选择直接在mysql workbench中建表
首先是员工表,本项目第一阶段仅仅操作这个表。五个属性分别是ID;员工姓名:ename(这里选择这个名字其实也是下下策,不知道为什么我选择name会在xml sql映射语句中和其他的字段显示不一样颜色);age:年龄 gender:性别 department:部门
其中PK是主键,NN是非空。
- 编写实体类,用于和数据库的字段一一对应。新建entity软件包,然后在下面新建一个Employee类。
然后编写代码,注意ID用Long(为后面大数据做准备,也可以Integer,最好不要用基本数据类型)
Alt+insert 生成get,set方法(按住Ctrl点击属性可以多选),生成toString方法
public class Employee {
@Id//表示该属性是主键
@GeneratedValue(strategy = GenerationType.IDENTITY)//指示 MyBatis 使用数据库的自增机制来生成主键值。
private Long id;
private String ename;
private Integer age;
private String gender;
public Employee(Long id, String ename, Integer age, String gender, String department) {
this.id = id;
this.ename = ename;
this.age = age;
this.gender = gender;
this.department = department;
}
public Employee(String ename, Integer age, String gender, String department) {
this.ename = ename;
this.age = age;
this.gender = gender;
this.department = department;
}
@ApiModelProperty(value = "部门")
private String department;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return ename;
}
public void setName(String ename) {
this.ename = ename;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
@Override
public String toString() {
return "Employee{" +
"id=" + id +
", name='" + ename + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
", department='" + department + '\'' +
'}';
}
}
- 根据需求在mapper接口中声明操作数据库的方法。新建dao软件包,在其中新建EmployeeMapper接口。
@Mapper
public interface EmployeeMapper {
//查找操作
Employee selectById(Long id);
List<Employee> selectByName_MH(String ename);
List<Employee> selectByDepartment_MH(String department);
List<DepartmentCount> getDepartmentCount();
//修改操作
Boolean updateEmployeeById(Employee employee);
//增加操作
Boolean insertEmployee(Employee employee);
//删除操作
Boolean deleteEmployeeById(Long id);
}
关于@mapper
这个注解一般使用在Dao层接口上,相当于一个mapper.xml文件,它的作用就是将接口生成一个动态代理类。加入了@Mapper注解,目的就是为了不再写mapper映射文件。这个注解就是用来映射mapper.xml文件的。
使用@mapper后,不需要在spring配置中设置扫描地址,通过mapper.xml里面的namespace属性对应相关的mapper类,spring将动态的生成Bean后注入到ServiceImpl中。
- 将声明的方法实现。在resource目录下新建mapper目录,再在下面新建employee-mapper.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="com.example.demo.dao.EmployeeMapper">
<!--指明为那个mapper服务,注意此处的包名一定要改成自己的-->
<select id="selectById" resultType="Employee">
<!--指明为哪个方法服务以及返回值类型-->
select id,ename,age,gender,department
from employee
where id = #{id}
</select>
<!--根据姓名模糊查找-->
<select id="selectByName_MH" resultType="Employee">
<!--指明为哪个方法服务以及返回值类型-->
select id,ename,age,gender,department
from employee
where ename like CONCAT('%', #{ename}, '%')
</select>
<select id="getDepartmentCount" resultType="DepartmentCount">
SELECT department, COUNT(*) AS count
FROM employee
GROUP BY department
</select>
<!--模糊搜索根据部门查询下属人员状况-->
<select id="selectByDepartment_MH" resultType="Employee">
<!-- 指明为哪个方法服务以及返回值类型 -->
select id, ename, age, gender, department
from employee
where department like CONCAT('%', #{department}, '%')
</select>
<!--插入员工-->
<insert id="insertEmployee" parameterType="Employee">
INSERT INTO employee (ename, age, gender, department)
VALUES (#{ename}, #{age}, #{gender}, #{department})
</insert>
<!--更新员工-->
<update id="updateEmployeeById" parameterType="Employee">
UPDATE employee
SET ename = #{ename}, age = #{age}, gender = #{gender}, department = #{department}
WHERE id = #{id}
</update>
<!--删除操作-->
<delete id="deleteEmployeeById" parameterType="Long">
DELETE FROM employee
WHERE id = #{id}
</delete>
</mapper>
这些SQL语句,我本身还没学,均为模仿或者询问GPT。
- 数据库相关的操作已经搞定了,下面就是有关于Service层和Controller层的内容了。Service这一层的作用是调用mapper里面的方法进而实现比较复杂的业务逻辑。Service是用来服务的,相当于底层操作数据库的curd方法和上层高级方法的中间件。controller是为前端提供的访问入口,不用关心具体的业务逻辑。具体的业务逻辑放在了service里,controller只需调用它封装好的方法即可。
@Service
public class EmployeeService {
@Autowired //注入依赖
private EmployeeMapper employeeMapper;
/**
* 获取数据库所有员工信息,然后挨个存在hashmap中
* 就可以获得部门对应员工信息,直接打印的没有返回值。
*/
public Map<String, Integer> numberOfDepartment(){
int len = employeeMapper.getRowCount();
Map<String, Integer> departmentCount = new HashMap<>();//创建哈希键值对存储部门,员工数据
for (int i = 1; i <= len; i++) {//循环得到所有的员工数据
Employee e = employeeMapper.selectById(i);
String department=e.getDepartment();
if (departmentCount.containsKey(department)) {//如果部门已经存在
departmentCount.put(department, departmentCount.get(department) + 1);
}
// 如果部门不存在,则初始化员工数量为1
else {
departmentCount.put(department, 1);
}
}
// System.out.println("部门数量是: " + departmentCount.size());
// for (Map.Entry<String, Integer> entry : departmentCount.entrySet()) {
// String department = entry.getKey();
// int employeeCount = entry.getValue();
// System.out.println("部门:" + department + ",员工数量:" + employeeCount);
// }
return departmentCount;
}
/**
* 本函数实现根据部门名称查询部门人数
* @param department 部门名称
* @return 输入部门下的人数
*/
public int employeeOfDepartment(String department){
List<Employee> list =employeeMapper.selectByDepartment(department);
int count =0;
for (Employee e: list){
System.out.println(e);
count+=1;
}
return count;
}
public List getByDepartment_MH(String department){
List<Employee> list =employeeMapper.selectByDepartment_MH(department);
return list;
}
/**
* 根据员工姓名获取员工信息
*/
public Employee getByName(String name){
return employeeMapper.selectByName(name);
}
public List<Employee> getByName_MH(String name){
List<Employee> list =employeeMapper.selectByName_MH(name);
return list;
}
}
@Api("Hello控制类")
@RestController
public class EmployeeController {
@Autowired //注入业务层
private EmployeeService employeeService;
@ApiOperation("根据姓名查找员工信息")
@PostMapping("/1")
public String hello3(@ApiParam("员工名") @RequestParam("name") String name){
return employeeService.getByName(name).toString();
}
@ApiOperation("根据姓名模糊查找员工信息")
@PostMapping("/2")
public String hello4(@ApiParam("员工名") @RequestParam("name") String name){
return employeeService.getByName_MH(name).toString();
}
@ApiOperation("根据部门名称获取部门员工人数")
@PostMapping("/3")
public String hello5(@ApiParam("部门名") @RequestParam("department") String department){
return String.valueOf(employeeService.employeeOfDepartment(department));
}
@ApiOperation("获得部门数量")
@GetMapping("/4")
//打印员工信息尚未处理,循环打印怎么解决???
public String hello5(){
Map<String, Integer> departmentCount = employeeService.numberOfDepartment();
return ("部门数量是:"+departmentCount.size());
}
@ApiOperation("获得所有部门员工人数")
@GetMapping("/6")
public String hello7(){
Map<String, Integer> departmentCount = employeeService.numberOfDepartment();
String count = departmentCount.toString();
count = count.replace(",", "\n");
count = count.substring(1, count.length() - 1);
return (count);
}
@ApiOperation("根据部门名称模糊获取部门员工信息")
@PostMapping("/5")
public String hello6(@ApiParam("部门名") @RequestParam("department") String department){
List list = employeeService.getByDepartment_MH(department);
String listString = list.toString();
listString = listString.replace(",", "\n");
listString = listString.substring(1, listString.length() - 1);
return listString;
}
}
这里用到了新的注解,@Api,@ApiOperation是来源于Swagger插件。这个插件用来生成前端测试文档(也可以在test文件夹@test测试,但是逼格看起来不够高)
使用此插件,首先在https://mvnrepository.com/ maven仓库找到这个插件,然后复制依赖信息到pom.xml,maven管理工具就会下载依赖。
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.5.0</version>
</dependency>
然后编写swagger配置类,用于建立连接并生成一些相关信息。
@EnableSwagger2
@Configuration
public class Swagger2Config {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//为当前包路径,控制器类包
.apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
.paths(PathSelectors.any())
.build();
}
//构建 api文档的详细信息函数
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
//页面标题
.title("xxxx人员信息平台API接口文档")
//创建人
.contact(new Contact("陈xx", "https://www.xxxx.edu.cn",
"1687520xxx@qq.com"))
//版本号
.version("1.0")
//描述
.description("work1接口测试")
.build();
}
}
最终,启动主程序。浏览器访问Swagger UI
到此结束(仅仅是简单版,后面又建了部门表没有在此继续写)
结语
小白入门坑太多,哎,每个人踩的坑害都不一样。算是真真实实完成了一个比较小项目,总算也是踏出去第一步,未来可期,加油!
不过说真的,做项目接触了好多东西,大大激发了我的学习欲望。JavaSE+MySQL+SpringBoot框架,开学!
n(“1.0”)
//描述
.description(“work1接口测试”)
.build();
}
}
最终,启动主程序。浏览器访问[Swagger UI](http://127.0.0.1:8080/swagger-ui.html#/)
[外链图片转存中...(img-8WjTaMgu-1698993532699)]
[外链图片转存中...(img-YVxBMEeC-1698993532699)]
[外链图片转存中...(img-XxsD95vy-1698993532700)]
到此结束(仅仅是简单版,后面又建了部门表没有在此继续写)
**结语**
小白入门坑太多,哎,每个人踩的坑害都不一样。算是真真实实完成了一个比较小项目,总算也是踏出去第一步,未来可期,加油!
不过说真的,做项目接触了好多东西,大大激发了我的学习欲望。JavaSE+MySQL+SpringBoot框架,开学!