CMIPT/gcs-back-end

[WIP] 完成数据库表的 CRUD 功能

Opened this issue · 1 comments

目前一共有两张表,我们需要为这两张表设计相关的接口和功能,下面我以设计一个创建用户的 RESTful 风格的接口为例。

首先,我们需要创建一个 PO 对象(Persistent Object) 用来和数据库进行完全关联,表中字段的下划线命名全部转换成小驼峰命名,例如 user_password 需要转换成 userPassword 这样可以不用书写 @TableField 注解,所有的 PO 对象都应该以 PO 后缀结尾,所以我们可以得到以下的代码:

@Data
@AllArgsConstructor
@TableName("t_user")
public class UserPO {
    private Long id;
    private String username;
    private String email;
    private String userPassword;
    private LocalDateTime gmtCreated;
    private LocalDateTime gmtUpdated;
    @TableLogic
    private LocalDateTime gmtDeleted;
    public UserPO(UserDTO userDTO) {
        this.id = userDTO.getId();
        this.username = userDTO.getUsername();
        this.email = userDTO.getEmail();
        this.userPassword = MD5Converter.convertToMD5(userDTO.getUserPassword());
    }
}

需要说明的几点:

  • bigintjava 中对应为 Long
  • varcharchar 等对应为 String
  • datatime 对应为 LocalDateTime
  • @Date 注解会自动帮我们添加 setter, getter, equals等方法。
  • @AllArgsConstructor 会自动添加一个包含所有字段的构造器。
  • @TableName("t_user") 用于指定数据库表的名字,如果没有该字段,那么 MyBatis-Plus 会使用 user_p_o 作为表名。
  • 在开发中我们往往不会直接从前端接收 PO 对象,而是接收 DTO 对象,在本例中前端实际上并不需要传输 gmt_* 这些数据由数据库自动生成。

UserDTO 对象的代码如下:

@Data
public class UserDTO {
    private Long id;
    private String username;
    private String email;
    private String userPassword;
}

更多的注意事项可以在开发实录中的mybatis-plus部分查看。

紧接着我们需要添加一个 mapper 用于 cruid, 由于使用了 mybatis-plus, 我们几乎不需要编写 sql 代码(文件名均以 Mapper.java 结尾):

public interface UserMapper extends BaseMapper<UserPO> {}

紧接着我们可以需要创建 service 代码(文件名均以 Service.java 结尾):

public interface UserService extends IService<UserPO> {}

接下来我们需要编写 controller 类(文件名均以 Controller.java 结尾):

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @PostMapping
    public ResponseEntity<Void> createUser(@RequestBody UserDTO user) {
        if (user == null ||
            user.getUsername() == null ||
            user.getEmail() == null ||
            user.getUserPassword() == null) {
            return ResponseEntity.badRequest().build();
        }
        // there may be some check before....
        boolean res = userService.save(new UserPO(user));
        if (res) {
            return ResponseEntity.ok().build();
        } else {
            return ResponseEntity.badRequest().build();
        }
    }
}

由于 mybatis-plus 提供了一些默认方法,所以我们需要实现的部分很少,我们往往需要进行参数的检查,执行结果的检查等。

上面的代码是一次简单的实例,我们需要思考哪些功能会被用到,需要设计哪些 api, 在 api 中需要做哪些检查等。

上述使用了 mvc 的设计模式,其中 controller 主要进行逻辑的检查,而 service 则对业务实际需要的功能进行封装,而 dao (也就是 mapper)才是真正和数据库进行交互的对象。

如果你认为 mybatis-plus 提供的默认功能不能完全满足你的需求,你可以在 UserService 中增加新的功能,并通过创建一个子类去实现该接口实现该功能,例如:

package edu.cmipt.gcs.service;

import com.baomidou.mybatisplus.extension.service.IService;

import edu.cmipt.gcs.pojo.UserPO;

public interface UserService extends IService<UserPO> {
    void test();
}

接下来创建一个 UserServiceImpl 类:

package edu.cmipt.gcs.service;

import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import edu.cmipt.gcs.dao.UserMapper;
import edu.cmipt.gcs.pojo.UserPO;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserPO> implements UserService {
    @Override
    public void test() {
        System.out.println("test");
    }
}

在这个类中,我们需要继承 ServiceImpl<UserMapper, UserPO> 这个类提供 IService 接口的实现,我们还需要实现 UserService 以自定义我们的方法,进行上述操作后,在自动装配后就会创建 UserServiceImple 的对象而不是默认的 ServiceImpl<UserMapper, UserPO> 对象。

完成上面的代码后,你还需要编写 Open API 文档,这篇文章提供了该例子的说明:spring-doc使用 或者你可以查看 pr: #33

本次任务不会给出任何的需求分析,需要参与者自行进行需求的讨论,需要尽可能的设计能够满足需求的接口。参与者自行讨论并分配任务。

注意:如果需要返回对象(例如查询一个用户信息),那么应该单独创建一个 UserVO 对象用于返回值的传递,简单来说从前端接收的数据采用 DTOData Transfer Object) 作为后缀, 而发送给前端的数据采用 VO ( View Object ) 作为后缀。可以有多个 VO 对象,例如同样可以增加一个 UserRepositoryListVO 对象表示一个用户及其创建的所有(或部分)仓库。

查看 [WIP] v0.1.0特性介绍 获取完整进度。