基于Maven+ SpringMVC+ MyBatis +Druid+MySql员工管理系统新手教程


基于Maven+ SpringMVC+ MyBatis +Druid+MySql员工管理系统新手教程

前言

百度上搜这个还能跳出来个100+RMB的课程。这课有好多人看。我看了一下目录,发现大概比我的系统全面。但是,如果你只是要使用这些工具搭建一个员工管理系统,看我的就够了。虽然我只是个新手,但是我实现了,并且尽我所能讲清楚代码。

项目目标

我们搭建的员工管理系统是要有员工,部门和员工,部门的关系和对前三者在应用场景下的增删改查。

具体来说,对于员工和部门的增删改查是较简单的。只需注意增时要保证员工或部门不存在,删时保证员工或部门存在,改时保证员工或部门存在并且查时能用名字或id查找。对于两者关系的增删改查稍微变了些东西。查的时候通过部门名字查找所有该部门的员工信息,包括员工个数并且这些员工和部门要存在且id一致。

工具介绍

Maven是用来下各种各样jar包的。

SpringMVC

这是个设计框架。主要由模块层(Model),视图层(View)和控制层(controller)组成。

模块层封装了数据与进行数据进行处理的代码,是实际经行数据处理的地方,也是与数据库交互的地方。我的代码里包括Service,ServiceImpl和Mapper来处理数据。其实,在写这个项目时,大可不必分这么多层,会显得徒增代码量,但是这是个要养成的好习惯,至少要知道分层思想。

视图层负责将应用显示给用户和显示模型的状态。这主要是前端干的事,和我后端无瓜。我们的视图由Navicat解决。

控制层负责视图和模型之间的交互,把用户的请求发送到对应的模型上,并把模型的改变及时反应到视图上。

Mysql

这是个数据库。结构从上到下依次是数据库(database)和表(table)

Mybatis

我们java程序中存储的数据是对象,怎么把对象转化成mysql中的表呢?靠的就是mybatis。

Druid

这是一个数据传输时的连接池。用这个是为了数据传输时加速与省消耗。以前每次连接数据库都要建立联系,就像每次回家,都要买辆车;如果用连接池,它会把我们数据传输时用的放进去,要用时从里面拿就行了,就像共享单车。

具体的点之后和代码一起补充。

我使用的是IDEA(编程),Postman(调用接口)和Navicat(mysql数据可视化)。

其中Navicat还提供直接用Mysql命令操作数据库的功能。菜单里点击Query,再点击newQuery,就能直接写Mysql语句来验证程序里的命令是否正确。非常方便。

开始制作

创建Mysql表

如果你是在本地玩,需要在本地先起一个Mysql服务。我下了个5开头的版本。

https://dev.mysql.com/downloads/file/?id=506120

在Navicat上连接Mysql。先创建个Mysql的数据库。记住你的数据库名,之后要用。

Pom.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-parent</artifactId>

<version>2.5.2</version>

<relativePath/><!--lookupparentfromrepository-->

</parent>

<groupId>com.vue</groupId>

<artifactId>mybatis_druid_mysql</artifactId>

<version>0.0.1-SNAPSHOT</version>

<name>mybatis_druid_mysql</name>

<description>mybatis_druid_mysql</description>

<properties>

<java.version>1.8</java.version>

</properties>

<dependencies>

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

</dependency>

<!--web依赖,包含servlet,内置tomcat等-->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-web</artifactId>

</dependency>

<!--mysql依赖-->

<dependency>

<groupId>mysql</groupId>

<artifactId>mysql-connector-java</artifactId>

<scope>runtime</scope>

</dependency>

<!--mybatis依赖-->

<dependency>

<groupId>org.mybatis.spring.boot</groupId>

<artifactId>mybatis-spring-boot-starter</artifactId>

<version>1.3.2</version>

</dependency>

<!--druid依赖包,配合springBoot项目使用-->

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid-spring-boot-starter</artifactId>

<version>1.1.14</version>

</dependency>

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

</dependency>

</dependencies>

<build>

<plugins>

<plugin>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-maven-plugin</artifactId>

</plugin>

</plugins>

</build>

</project>

启动类

@Service

@SpringBootApplication

@MapperScan("/com.mybatis_druid_mysql.demo.Mapper")

publicclassDemoApplication{

publicstaticvoidmain(String[]args){

SpringApplication.run(DemoApplication.class,args);

   }

}

与以往不同,多了个@MapperScan。它在用到java配置时登记Mybatis的Mapper接口。

Druid连接

就像上文提及,druid像共享单车。那么我们就要规定各项指标,比如有多少单车,每条车可以骑多久等等。

application.properties配置文件

server.port=18001

spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver

spring.datasource.druid.url=(1)

spring.datasource.druid.username=root

spring.datasource.druid.password=password

spring.datasource.druid.initial-size=5

spring.datasource.druid.max-active=20

spring.datasource.druid.min-idle=5

spring.datasource.druid.max-wait=60000

spring.datasource.druid.timeBetweenEvictionRunsMillis=60000

spring.datasource.druid.minEvictableIdleTimeMillis=300000

spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize=200

第一行是我们程序的端口。

(1) 这里是你的mysql数据库的url,形如:jdbc:mysql://127.0.0.1/db_example?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false

其中,db_example是数据库的名字。?后面代表一些参数。

第五行开始就是一些各种各样的druid设置。

怎么样让程序调用上这些配置呢?

packagecom.mybatis_druid_mysql.demo.Druid;

importcom.alibaba.druid.pool.DruidDataSource;

importorg.springframework.beans.factory.annotation.Value;

importorg.springframework.boot.SpringBootConfiguration;

importorg.springframework.context.annotation.Bean;

importorg.springframework.context.annotation.PropertySource;

importorg.springframework.transaction.annotation.EnableTransactionManagement;

importjavax.sql.DataSource;

@SpringBootConfiguration

@PropertySource(value="classpath:/application.properties")

@EnableTransactionManagement

publicclassDruid{

@Value("${spring.datasource.druid.username}")

privateStringuserName;

@Value("${spring.datasource.druid.password}")

privateStringpassword;

@Value("${spring.datasource.druid.driver-class-name}")

privateStringdriverName;

@Value("${spring.datasource.druid.url}")

privateStringurl;

@Value("${spring.datasource.druid.initial-size}")

privateintinitialSize;

@Value("${spring.datasource.druid.max-active}")

privateintmaxActive;

@Value("${spring.datasource.druid.min-idle}")

privateintminIdle;

@Value("${spring.datasource.druid.max-wait}")

privateintmaxWait;

@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")

privateinttimeBetweenEvictionRunsMillis;

@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")

privateintminEvictableIdleTimeMillis;

@Value("${spring.datasource.druid.maxPoolPreparedStatementPerConnectionSize}")

privateintmaxPoolPreparedStatementPerConnectionSize;

@Bean(name="datasource")

publicDataSourcedataSource(){//由druid-spring-boot-starter实现springboot提供的datasource接口

DruidDataSourcedataSource=null;

try{

dataSource=newDruidDataSource();

dataSource.setUsername(userName);

dataSource.setPassword(password);

dataSource.setUrl(url);

dataSource.setDriverClassName(driverName);

dataSource.setInitialSize(initialSize);

dataSource.setMaxActive(maxActive);

dataSource.setMinIdle(minIdle);

dataSource.setMaxWait(maxWait);

dataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

dataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);

dataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);

}catch(Exceptione){

e.printStackTrace();

       }

returndataSource;

   }

}

@SpringBootConfiguration注释是一个类级别的注释,它指示此类提供了应用程序配置。

@PropertySource(value = "classpath:/application.properties")注释是一个读取properties配置文件属性的注释,塔指示了配置文件地址。

@EnableTransactionManagement注释是一个事务管理注解。

@Value注释是一个从属性源取值的注释,它后面写注释源的名称。

上面代码设置了dataSource。之后就会交给druid-spring-boot-starter这个依赖处理。

这样,Druid就连接完成啦!

Entity创建

实体(Entity)定义了我们数据的基本结构。比如,我们这里要做3张表:员工信息表,部门信息表和员工部门关系表。

Employee

@Entity(name="employee")

@Data

publicclassEmployee{

@Id

Longid;

Stringname;

Stringsex;

Stringaddress;

}

@Entity(name = "employee")注释说明这是一个实体,而且名字叫employee。

@Data注释说明这是一个数据,它代替了普通的getter和setter。

@Id注释说明这是这个实体的主键(primary key)。

Department

@Entity(name="department")

@Data

publicclassDepartment{

@Id

Longdepartment_id;

Stringdepartment_name;

}

Connection

@Entity(name="connection")

@Data

publicclassConnection{

@Id

Longconnection_id;

Longdepartment_id;

Longemployee_id;

Stringemployee_name;

Stringdepartment_name;

}

数据处理

从端口调用接口到实现数据的增上改查(CRUD),是怎么实现的呢?

我的总共个分为这么几层:Controller->Service->ServiceImpl->Mapper。正规一点还要加上一层Dao层。

Controller

@RestController

@RequestMapping("/jerry")

@Slf4j

publicclassController{

@Autowired

privateServiceservice;

@PostMapping(value="/insertEmployee",produces=MediaType.APPLICATION_JSON_UTF8_VALUE,

consumes=MediaType.APPLICATION_JSON_UTF8_VALUE)

publicEmployeeinsertEmployee(@RequestBodyEmployeeemployee){

if(service.countEmployee(employee)==0)

service.insertEmployee(employee);

returnemployee;

   }

@DeleteMapping("/deleteEmployee")

publicStringdeleteEmployee(@RequestParamStringid){

service.deleteEmployee(id);

return"deleted";

   }

@PutMapping(value="/updateEmployee",produces=MediaType.APPLICATION_JSON_UTF8_VALUE,

consumes=MediaType.APPLICATION_JSON_UTF8_VALUE)

publicEmployeeupdateEmployee(@RequestParamLongid,@RequestBodyEmployeeemployee){

employee.setId(id);

service.updateEmployee(employee);

log.info("result: {}",employee);//打印日志

returnemployee;

   }

@GetMapping(value="/searchEmployee",produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

publicEmployeesearchEmployee(@RequestParam("id")Stringid){

returnservice.searchEmployee(id);

   }

@PostMapping(value="/addDepartment",produces=MediaType.APPLICATION_JSON_UTF8_VALUE,

consumes=MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

publicDepartmentaddDepartment(@RequestBodyDepartmentdepartment){

if(service.countDepartment(department)==0)

service.addDepartment(department);

returndepartment;

   }

@DeleteMapping("/deleteDepartment")

@ResponseBody

publicStringdeleteDepartment(@RequestParamLongdepartment_id){

service.deleteDepartment(department_id);

return"deleted";

   }

@GetMapping(value="/searchDepartment",produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

publicDepartmentsearchDepartment(@RequestParam("department_id")Stringdepartment_id){

log.info("result: {}",service.searchDepartment(department_id));//打印日志

Departmentdepartment=service.searchDepartment(department_id);

returnservice.searchDepartment(department_id);

   }

@PutMapping(value="/updateDepartment",produces=MediaType.APPLICATION_JSON_UTF8_VALUE,

consumes=MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

publicDepartmentupdateDepartment(@RequestParamLongdepartment_id,@RequestBodyDepartmentdepartment){

department.setDepartment_id(department_id);

service.updateDepartment(department);

returndepartment;

   }

@RequestMapping(value="/addConnection",produces=MediaType.APPLICATION_JSON_UTF8_VALUE,

consumes=MediaType.APPLICATION_JSON_UTF8_VALUE)

@ResponseBody

publicConnectionaddConnection(@RequestBodyConnectionconnection){

if(service.countConnection(connection)==0&&(service.employeeExistAndIdCorrect(connection)==1

&&(service.departmentExistAndIdCorrect(connection)==1)))

service.addConnection(connection);

returnconnection;

   }

@RequestMapping("/deleteConnection")

@ResponseBody

publicStringdeleteConnection(Longconnection_id){

service.deleteConnection(connection_id);

return"deleted";

   }

@RequestMapping("/deleteEmployeeFromDepartment")

@ResponseBody

publicStringdeleteEmployeeFromDepartment(@RequestParam("employee_id")Longemployee_id,@RequestParam("department_id")Longdepartment_id){

service.deleteEmployeeFromDepartment(employee_id,department_id);

return"deleted";

   }

@RequestMapping("/updateConnection")

@ResponseBody

publicStringupdateConnection(@RequestBodyConnectionconnection,@RequestParamLongconnection_id){

connection.setConnection_id(connection_id);

service.updateConnection(connection);

return"updated";

   }

@RequestMapping("/searchEmployeeFromDepartment")

@ResponseBody

publicList<Connection>searchEmployeeFromDepartment(Stringdepartment_name){

returnservice.searchEmployeeFromDepartment(department_name);

   }

@RequestMapping("/searchDepartmentFromEmployee")

@ResponseBody

publicList<Connection>searchDepartmentFromEmployee(Stringemployee_name){

returnservice.searchDepartmentFromEmployee(employee_name);

   }

@RequestMapping("/countEmployeeFromDepartment")

@ResponseBody

publicLongcountEmployeeFromDepartment(Stringdepartment_name){

returnservice.countEmployeeFromDepartment(department_name);

   }

}

@RestController注释是一个连接了两种其他注释的注释,他们分别是@Controller@ResponseBody,前者告诉系统这是个控制类,并且暗含@Component能被系统扫描到;后者告诉系统这里返回的数据以网络反应体(web response body)展示的,不是普通的返回数据。

@RequestMapping("/jerry")注释是一个引导网络请求到请求处理类的注释,它定义了调用接口时的路径。

@Slf4j注释是一个来自lombok依赖的注释,他能打印日志。

@Autowired注释是一个自动导航的注释,它能把@Component注释下的类纳为己用。

@PostMapping注释是@RequestMapping的一种,它要求请求时用Post方法调用。这种方法通常用在增删改查中的

@DeleteMapping注释是@RequestMapping的一种,它要求请求时用Delete方法调用。这种方法通常用在增删改查中的

@PutMapping注释是@RequestMapping的一种,它要求请求时用Put方法调用。这种方法通常用在增删改查中的

@GetMapping注释是@RequestMapping的一种,它要求请求时用Get方法调用。这种方法通常用在增删改查中的

以上四者都能定义请求调用时的路径和输入输出的数据形式。比如Json形式,方便观察。

我代码中前面还是挺规范,到后面全是@RequestMapping,这不好。

@RequestParam@RequestBody都是定义网络请求参数名称,前者参数是普通参数(parameter),比如String或Long;后者参数是一个类。

我代码中前面还是挺规范,到后面全都漏了,这不好。

你可能注意到了,我的所有实体的属性都是小写,单词之间由下划线分开。比如department_name。这是因为如果不这么做,Mysql会自动把这些属性转化成表中的Title时,自动变小写,单词用下划线分开。按理说分开就分开,但是我试了一下,会引起一个我搞不懂的bug。于是就向Mysql妥协。

Service

这就是个接口类,由ServiceImpl实现。

@org.springframework.stereotype.Service

publicinterfaceService{

publicvoidinsertEmployee(Employeeemployee);

publicLongcountEmployee(Employeeemployee);

publicvoiddeleteEmployee(Stringid);

publicvoidupdateEmployee(Employeeemployee);

publicEmployeesearchEmployee(Stringid);

publicvoidaddDepartment(Departmentdepartment);

publicLongcountDepartment(Departmentdepartment);

publicvoiddeleteDepartment(Longdepartment_id);

publicDepartmentsearchDepartment(Stringdepartment_id);

publicvoidupdateDepartment(Departmentdepartment);

publicvoidaddConnection(Connectionconnection);

publicLongcountConnection(Connectionconnection);

publicvoiddeleteConnection(Longconnection_id);

publicvoidupdateConnection(Connectionconnection);

publicList<Connection>searchEmployeeFromDepartment(Stringdepartment_id);

publicList<Connection>searchDepartmentFromEmployee(Stringemployee_name);

publicLongcountEmployeeFromDepartment(Stringdepartment_name);

publicvoiddeleteEmployeeFromDepartment(Longemployee_id,Longdepartment_id);

publicLongemployeeExistAndIdCorrect(@Param("connection")Connectionconnection);

publicLongdepartmentExistAndIdCorrect(@Param("connection")Connectionconnection);

}

@Service注释是一个指明该类是个独立服务层的注释,它是@Component的一种,能被扫描到

这里它变成@org.springframework.stereotype.Service这么长,是因为我的类名也是Service,系统为了区分,就写长了。

ServiceImpl

@org.springframework.stereotype.Service

@Transactional

publicclassServiceImplimplementsService{

@Autowired

privateMappermapper;

publicvoidinsertEmployee(Employeeemployee){

mapper.insertEmployee(employee);

   }

publicLongcountEmployee(Employeeemployee){

returnmapper.countEmployee(employee);

   }

publicvoiddeleteEmployee(Stringid){

mapper.deleteEmployee(id);

   }

publicvoidupdateEmployee(Employeeemployee){

mapper.updateEmployee(employee);

   }

publicEmployeesearchEmployee(Stringid){

returnmapper.searchEmployee(id);

   }

publicvoidaddDepartment(Departmentdepartment){

mapper.addDepartment(department);

   }

publicLongcountDepartment(Departmentdepartment){returnmapper.countDepartment(department);}

publicvoiddeleteDepartment(Longdepartment_id){

mapper.deleteDepartment(department_id);

   }

publicDepartmentsearchDepartment(Stringdepartment_id){

returnmapper.searchDepartment(department_id);

   }

publicvoidupdateDepartment(Departmentdepartment){

mapper.updateDepartment(department);

   }

publicvoidaddConnection(Connectionconnection){

mapper.addConnection(connection);

   }

publicLongcountConnection(Connectionconnection){returnmapper.countConnection(connection);}

publicvoiddeleteConnection(Longconnection_id){

mapper.deleteConnection(connection_id);

   }

publicvoidupdateConnection(Connectionconnection){

mapper.updateConnection(connection);

   }

publicList<Connection>searchDepartmentFromEmployee(Stringemployee_name){

returnmapper.searchDepartmentFromEmployee(employee_name);

   }

publicList<Connection>searchEmployeeFromDepartment(Stringdepartment_name){

returnmapper.searchEmployeeFromDepartment(department_name);

   }

publicLongcountEmployeeFromDepartment(Stringdepartment_name){

returnmapper.countEmployeeFromDepartment(department_name);

   }

publicvoiddeleteEmployeeFromDepartment(Longemployee_id,Longdepartment_id){

mapper.deleteEmployeeFromDepartment(employee_id,department_id);

   }

publicLongemployeeExistAndIdCorrect(@Param("connection")Connectionconnection){

returnmapper.employeeExistAndIdCorrect(connection);

   }

publicLongdepartmentExistAndIdCorrect(@Param("connection")Connectionconnection){

returnmapper.departmentExistAndIdCorrect(connection);

   }

}

@Transactional注释是一个为独立方法或一个类的转换属性的注释。

Mapper

使用Mysql命令,用于将对象与Mysql里的表打交道。

@org.apache.ibatis.annotations.Mapper

publicinterfaceMapper{

@Insert("insert into employee(name,sex,address) values(#{name},#{sex},#{address})")

@Options(useGeneratedKeys=true,keyColumn="id")//展示id

voidinsertEmployee(Employeeemployee);

@Select("select count(*) from employee where name = #{name}")

LongcountEmployee(Employeeemployee);

@Delete("delete from employee where id = #{id}")

voiddeleteEmployee(@Param("id")Stringid);

@Update("update employee set name = #{name},sex = #{sex},address = #{address} where id = #{id}")

@Options(useGeneratedKeys=true,keyColumn="id")

voidupdateEmployee(@Param("employee")Employeeemployee);

@Select("select * from employee where id = #{id}")

@Options(useGeneratedKeys=true,keyColumn="id")

EmployeesearchEmployee(@Param("id")Stringid);

@Insert("insert into department(department_name) values(#{department_name})")

@Options(useGeneratedKeys=true,keyProperty="department_id")

voidaddDepartment(Departmentdepartment);

@Select("select count(*) from department where department_name = #{department_name}")

LongcountDepartment(Departmentdepartment);

@Delete("delete from department where department_id = #{department_id}")

voiddeleteDepartment(@Param("department_id")Longdepartment_id);

@Select("select * from department where department_id = #{department_id}")

@Options(useGeneratedKeys=true,keyProperty="department_id")

DepartmentsearchDepartment(@Param("department_id")Stringdepartment_id);

@Update("update department set department_id = #{department_id}, department_name = #{department_name} where department_id = #{department_id}")

@Options(useGeneratedKeys=true,keyColumn="department_id",keyProperty="department_id")

voidupdateDepartment(@Param("department")Departmentdepartment);

@Insert("insert into connection(department_id,department_name,employee_id,employee_name)values(#{department_id},#{department_name},#{employee_id},#{employee_name})")

@Options(useGeneratedKeys=true,keyColumn="connection_id",keyProperty="connection_id")

voidaddConnection(Connectionconnection);

@Select("select count(*) from connection where department_name = #{department_name} and employee_name = #{employee_name}")

LongcountConnection(Connectionconnection);

@Delete("delete from connection where connection_id = #{connection_id}")

voiddeleteConnection(Longconnection_id);

@Delete("delete from connection where employee_id = #{employeeId} and department_id = #{department_id}")

voiddeleteEmployeeFromDepartment(@Param("employeeId")Longemployee_id,

@Param("department_id")Longdepartment_id);

@Update("update connection set employee_id = #{employee_id}, employee_id = #{employee_id}, department_id = #{department_id} , employee_name = #{employee_name} where connection_id = #{connection_id}")

@Options(useGeneratedKeys=true,keyColumn="connection_id",keyProperty="connection_id")

voidupdateConnection(Connectionconnection);

@Select("select * from connection where employee_name = #{employee_name}")

@Options(useGeneratedKeys=true,keyColumn="employee_name",keyProperty="employee_name")

List<Connection>searchDepartmentFromEmployee(Stringemployee_name);

@Select("select * from connection where department_name = #{department_name}")

@Options(useGeneratedKeys=true,keyColumn="department_name",keyProperty="department_name")

List<Connection>searchEmployeeFromDepartment(@Param("department_name")Stringdepartment_name);

@Select("select count(*) from connection where department_name = #{department_name}")

publicLongcountEmployeeFromDepartment(@Param("department_name")Stringdepartment_name);

@Select("select count(*) from employee where name = #{employee_name} and id = #{employee_id}")

publicLongemployeeExistAndIdCorrect(@Param("connection")Connectionconnection);

@Select("select count(*) from department where department_name = #{department_name} and department_id = #{department_id}")

publicLongdepartmentExistAndIdCorrect(@Param("connection")Connectionconnection);

}

以上括号内的语句就是Mysql命令,其相关意思网上多的很,我就不解释了。就算是新人也能通过字面意思与上文结合,猜知大概。

Navicat使用

其实这里应该与代码测试穿插着用,上文到这不是真正开始制作的顺序。

如果ENtity内写了表名,那么在最开始船舰的数据库下就会自动生成相应的表,以及该表的第一列;若没有,则手动生成。

在每次调用接口测试代码时,它会要求每张表都要有自增主键。于是,我们要右键表名,选择“Design Table”,选择相应主键,勾选自增(Auto-Increment)。

它刷新时间意不要用右键选择刷新,而要用底部的刷新键,或是重启Navicat。

注意事项

除了上文所提及的各种事项,我再整理一些修理bug的总结。

各种依赖包内的类别引用错了,很多都是同名的,注意选择你想要的。假如你和我一样对理论不熟悉,就要点开(“ctrl" + 左键)这些类一看究竟。有时他甚至不会一下显示这些同名的类,坑的我好惨。

写代码要规范,养成好习惯。有许多现在看来可写可不写的,那是因为我们程序功能简单。以后功能复杂起来,再不写规范,那就是一坨屎,不仅没人想看,自己过几天也不想看。

©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容