Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Kaiser-Yang opened this issue Aug 21, 2024 · 1 comment
Open

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

Kaiser-Yang opened this issue Aug 21, 2024 · 1 comment
Assignees
Labels
feature A new feature WIP Work-in-Progress

Comments

@Kaiser-Yang
Copy link
Contributor

Kaiser-Yang commented Aug 21, 2024

目前一共有两张表,我们需要为这两张表设计相关的接口和功能,下面我以设计一个创建用户的 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 对象表示一个用户及其创建的所有(或部分)仓库。

@Kaiser-Yang Kaiser-Yang added the feature A new feature label Aug 21, 2024
@Kaiser-Yang Kaiser-Yang changed the title 完成数据库表的 CFUD 功能 完成数据库表的 CRUD 功能 Aug 21, 2024
@Kaiser-Yang Kaiser-Yang changed the title 完成数据库表的 CRUD 功能 [WIP] 完成数据库表的 CRUD 功能 Aug 22, 2024
@Kaiser-Yang Kaiser-Yang added the WIP Work-in-Progress label Aug 22, 2024
@Quentin9922
Copy link

Quentin9922 commented Aug 30, 2024

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

Kaiser-Yang added a commit that referenced this issue Sep 12, 2024
We add a new function to get user info by name and add unit test for it.
Besides, we move the token to response header rather than response body.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 13, 2024
We add two APIs for checking the info validity, one is for checking the
username, the other is for checking the email.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 15, 2024
During development, we found that the `Long` can not be expressed
correctly in the `Swagger` document, so we use `String` to represent the
`id` and convert it to `Long` when we use it as the field of `UserPO`.

We also found that the `HttpServletRequest`'s `getReader()` and
`getInputStream()` can only be called once, so we need to cache the
request body in the `JwtFilter` to make it can be read multiple times.

During this commit, we update the header parameter `Token` with the
`Access-Token` and `Refresh-Token` to make it more clear.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 15, 2024
During development, we found that the `Long` can not be expressed
correctly in the `Swagger` document, so we use `String` to represent the
`id` and convert it to `Long` when we use it as the field of `UserPO`.

We also found that the `HttpServletRequest`'s `getReader()` and
`getInputStream()` can only be called once, so we need to cache the
request body in the `JwtFilter` to make it can be read multiple times.

During this commit, we update the header parameter `Token` with the
`Access-Token` and `Refresh-Token` to make it more clear.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 15, 2024
During development, we found that the `Long` can not be expressed
correctly in the `Swagger` document, so we use `String` to represent the
`id` and convert it to `Long` when we use it as the field of `UserPO`.

We also found that the `HttpServletRequest`'s `getReader()` and
`getInputStream()` can only be called once, so we need to cache the
request body in the `JwtFilter` to make it can be read multiple times.

During this commit, we update the header parameter `Token` with the
`Access-Token` and `Refresh-Token` to make it more clear.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 16, 2024
During development, we found that the `Long` can not be expressed
correctly in the `Swagger` document, so we use `String` to represent the
`id` and convert it to `Long` when we use it as the field of `UserPO`.

We also found that the `HttpServletRequest`'s `getReader()` and
`getInputStream()` can only be called once, so we need to cache the
request body in the `JwtFilter` to make it can be read multiple times.

During this commit, we update the header parameter `Token` with the
`Access-Token` and `Refresh-Token` to make it more clear.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 16, 2024
Kaiser-Yang added a commit that referenced this issue Sep 16, 2024
Kaiser-Yang added a commit that referenced this issue Sep 16, 2024
Kaiser-Yang added a commit that referenced this issue Sep 18, 2024
This API can also be used for getting other's repository list, but only
the public repository can be got.

The test case will be added after finishing the APIs related to
repository (such as creating a repository, updating a repository, etc.).

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 18, 2024
This API can also be used for getting other's repository list, but only
the public repository can be got.

The test case will be added after finishing the APIs related to
repository (such as creating a repository, updating a repository, etc.).

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 18, 2024
This API can also be used for getting other's repository list, but only
the public repository can be got.

The test case will be added after finishing the APIs related to
repository (such as creating a repository, updating a repository, etc.).

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 18, 2024
This API can also be used for getting other's repository list, but only
the public repository can be got.

The test case will be added after finishing the APIs related to
repository (such as creating a repository, updating a repository, etc.).

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 20, 2024
We finish the api for creating repository, and the test for it.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 20, 2024
We finish the api for creating repository, and the test for it.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 24, 2024
We finish the APIs related with ssh-key, including the following APIs:
* Upload a ssh-key
* Delete a ssh-key
* Get ssh-keys with pagination
* Update a ssh-key

We use spring transaction to ensure the atomicity of the operations.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 24, 2024
We finish the APIs related with ssh-key, including the following APIs:
* Upload a ssh-key
* Delete a ssh-key
* Get ssh-keys with pagination
* Update a ssh-key

We use spring transaction to ensure the atomicity of the operations.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 24, 2024
We finish the APIs related with ssh-key, including the following APIs:
* Upload a ssh-key
* Delete a ssh-key
* Get ssh-keys with pagination
* Update a ssh-key

We use spring transaction to ensure the atomicity of the operations.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 24, 2024
We finish the APIs related with ssh-key, including the following APIs:
* Upload a ssh-key
* Delete a ssh-key
* Get ssh-keys with pagination
* Update a ssh-key

We use spring transaction to ensure the atomicity of the operations.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 25, 2024
We finish the APIs related with ssh-key, including the following APIs:
* Upload a ssh-key
* Delete a ssh-key
* Get ssh-keys with pagination
* Update a ssh-key

We use spring transaction to ensure the atomicity of the operations.

See #32.
Kaiser-Yang added a commit that referenced this issue Sep 25, 2024
We finish the APIs for deleting and updating repository. For the
deleting user API, we now will remove all the ssh-keys uploaded by the
user, but not the repositories.

Besides, we find that we should not trust the data from the client side,
such as the `userId` from request body, we must get this data from the
database to check if the operation is allowed.

See #20 and #32.
Kaiser-Yang added a commit that referenced this issue Sep 25, 2024
We finish the APIs for deleting and updating repository. For the
deleting user API, we now will remove all the ssh-keys uploaded by the
user, but not the repositories.

Besides, we find that we should not trust the data from the client side,
such as the `userId` from request body, we must get this data from the
database to check if the operation is allowed.

See #20 and #32.
Kaiser-Yang added a commit that referenced this issue Sep 25, 2024
We finish the APIs for deleting and updating repository. For the
deleting user API, we now will remove all the ssh-keys uploaded by the
user, but not the repositories.

Besides, we find that we should not trust the data from the client side,
such as the `userId` from request body, we must get this data from the
database to check if the operation is allowed.

See #20 and #32.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A new feature WIP Work-in-Progress
Projects
None yet
Development

No branches or pull requests

4 participants