Browse Source

test: pipeline history buglist mapper

370774330@qq.com 5 years ago
parent
commit
b9b6dc5644

+ 4 - 3
web/src/main/java/seecoder/devcloud/web/controller/pipeline/DeploymentController.java

@@ -6,6 +6,7 @@ import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.common.exceptions.AccessDeniedException;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.Response;
 import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
 import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
 import seecoder.devcloud.web.service.pipeline.DeploymentService;
 import seecoder.devcloud.web.service.pipeline.DeploymentService;
@@ -32,7 +33,7 @@ public class DeploymentController {
     @ApiOperation(value = "获取项目所有部署的实例信息", httpMethod = "GET")
     @ApiOperation(value = "获取项目所有部署的实例信息", httpMethod = "GET")
     @ApiImplicitParam(name = "projectId", dataType ="int", paramType = "query")
     @ApiImplicitParam(name = "projectId", dataType ="int", paramType = "query")
     @GetMapping("/list")
     @GetMapping("/list")
-    public Response<List<DeploymentInfoVO>> retrieveDeploymentInfos(@RequestParam("projectId")Integer projectId){
+    public Response<List<DeploymentInfoVO>> retrieveDeploymentInfos(@RequestParam("projectId")Integer projectId) throws AccessDeniedException {
         return Response.buildSuccess(deploymentService.retrieveDeploymentInfos(projectId));
         return Response.buildSuccess(deploymentService.retrieveDeploymentInfos(projectId));
     }
     }
 
 
@@ -44,7 +45,7 @@ public class DeploymentController {
     })
     })
     @PostMapping
     @PostMapping
     public Response deploy(@RequestParam("projectId")Integer projectId,
     public Response deploy(@RequestParam("projectId")Integer projectId,
-                           @RequestParam("pipelineId")Integer pipelineId){
+                           @RequestParam("pipelineId")Integer pipelineId) throws AccessDeniedException {
         deploymentService.deploy(projectId,pipelineId);
         deploymentService.deploy(projectId,pipelineId);
         return Response.buildSuccess();
         return Response.buildSuccess();
     }
     }
@@ -56,7 +57,7 @@ public class DeploymentController {
     })
     })
     @DeleteMapping
     @DeleteMapping
     public Response delete(@RequestParam("projectId")Integer projectId,
     public Response delete(@RequestParam("projectId")Integer projectId,
-                @RequestParam("pipelineId")Integer pipelineId){
+                @RequestParam("pipelineId")Integer pipelineId) throws AccessDeniedException {
         deploymentService.deploy(projectId,pipelineId);
         deploymentService.deploy(projectId,pipelineId);
         return Response.buildSuccess();
         return Response.buildSuccess();
     }
     }

+ 12 - 5
web/src/main/java/seecoder/devcloud/web/dao/pipeline/PipelineHistoryMapper.java

@@ -1,7 +1,7 @@
 package seecoder.devcloud.web.dao.pipeline;
 package seecoder.devcloud.web.dao.pipeline;
 
 
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.*;
+import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
 import seecoder.devcloud.web.model.po.pipeline.PipelineHistoryPO;
 import seecoder.devcloud.web.model.po.pipeline.PipelineHistoryPO;
 
 
 import java.util.List;
 import java.util.List;
@@ -14,6 +14,11 @@ import java.util.List;
 @Mapper
 @Mapper
 public interface PipelineHistoryMapper {
 public interface PipelineHistoryMapper {
 
 
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    @Options(useGeneratedKeys = true, keyProperty = "param1.id", keyColumn = "id")
+    void insert(PipelineHistoryPO pipelineHistoryPO, String... ignoredCols);
+
+
     @Select("select * from pipeline_history where pipeline_id = #{pipelineId}")
     @Select("select * from pipeline_history where pipeline_id = #{pipelineId}")
     List<PipelineHistoryPO> selectByPipelineId(Integer pipelineId);
     List<PipelineHistoryPO> selectByPipelineId(Integer pipelineId);
 
 
@@ -21,14 +26,16 @@ public interface PipelineHistoryMapper {
     /**
     /**
      * 获取一个项目里所有流水线配置的最新构建历史
      * 获取一个项目里所有流水线配置的最新构建历史
      */
      */
-    @Select("SELECT *" +
+    @Select("<script>" +
+            "SELECT *" +
             "FROM   pipeline_history" +
             "FROM   pipeline_history" +
             "WHERE  startTime=" +
             "WHERE  startTime=" +
             "(  SELECT MAX(startTime) " +
             "(  SELECT MAX(startTime) " +
             "   FROM pipeline_history" +
             "   FROM pipeline_history" +
             "   WHERE pipeline_id in" +
             "   WHERE pipeline_id in" +
             "   <foreach collection='pipelineIds' open='(' item='pipelineId' separator=',' close=')'> #{pipelineId}</foreach>" +
             "   <foreach collection='pipelineIds' open='(' item='pipelineId' separator=',' close=')'> #{pipelineId}</foreach>" +
-            "   )")
-    List<PipelineHistoryPO> selectRecentlyHistoryBy(List<Integer> pipelineIds);
+            "   )" +
+            "</script>")
+    List<PipelineHistoryPO> selectPipelinesRecentlyHistory(@Param("pipelineIds") List<Integer> pipelineIds);
 
 
 }
 }

+ 2 - 4
web/src/main/java/seecoder/devcloud/web/dao/project/BugListMapper.java

@@ -1,9 +1,6 @@
 package seecoder.devcloud.web.dao.project;
 package seecoder.devcloud.web.dao.project;
 
 
-import org.apache.ibatis.annotations.InsertProvider;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Select;
-import org.apache.ibatis.annotations.UpdateProvider;
+import org.apache.ibatis.annotations.*;
 import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
 import seecoder.devcloud.web.dao.provider.GeneralInsertUpdateSqlProvider;
 import seecoder.devcloud.web.model.po.project.BugListPO;
 import seecoder.devcloud.web.model.po.project.BugListPO;
 
 
@@ -18,6 +15,7 @@ import java.util.List;
 public interface BugListMapper {
 public interface BugListMapper {
 
 
     @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
     @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    @Options(useGeneratedKeys = true, keyProperty = "param1.id", keyColumn = "id")
     int insert(BugListPO bugListPO, String... ignoredCols);
     int insert(BugListPO bugListPO, String... ignoredCols);
 
 
     @UpdateProvider(type= GeneralInsertUpdateSqlProvider.class, method="updateById")
     @UpdateProvider(type= GeneralInsertUpdateSqlProvider.class, method="updateById")

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/dao/project/ProjectMapper.java

@@ -19,7 +19,7 @@ public interface ProjectMapper {
     int updateProject(ProjectPO projectPO);
     int updateProject(ProjectPO projectPO);
 
 
     @Select("select * from project where group_id=#{groupId}")
     @Select("select * from project where group_id=#{groupId}")
-    @ResultMap(value = "projectMap")
+    //@ResultMap(value = "projectMap")
     List<ProjectPO> listProjectsByGroupId(int groupId);
     List<ProjectPO> listProjectsByGroupId(int groupId);
 
 
     @Select("select * from project where project_id in (select project_id from project_user where user_id=#{userId}")
     @Select("select * from project where project_id in (select project_id from project_user where user_id=#{userId}")

+ 3 - 2
web/src/main/java/seecoder/devcloud/web/dao/provider/GeneralInsertUpdateSqlProvider.java

@@ -11,8 +11,7 @@ import java.util.stream.Collectors;
  * @author PuHong Weng
  * @author PuHong Weng
  * @date 2021/3/1
  * @date 2021/3/1
  * @description: 避免写繁琐的插入和更新的方法的,注意 pojo类的字段要和数据库表对应, 用法示例见 UserMapperImpl.class
  * @description: 避免写繁琐的插入和更新的方法的,注意 pojo类的字段要和数据库表对应, 用法示例见 UserMapperImpl.class
- * 插入单个参数(除了ignoredCols以外的参数)时,mapper写方法就行,实例见 UserMapperImpl.insert
- * 插入多个参数(除了ignoredCols以外的参数)时,mapper方法参数要加@Param说明,实例见 GroupMemberMapper.insert
+
  */
  */
 public class GeneralInsertUpdateSqlProvider {
 public class GeneralInsertUpdateSqlProvider {
 
 
@@ -20,6 +19,8 @@ public class GeneralInsertUpdateSqlProvider {
      * @param obj 插入对象, 用来获取字段和表名
      * @param obj 插入对象, 用来获取字段和表名
      * @param ignoredCols 插入时需要忽略的列名 列名格式是Underscore,如created_at
      * @param ignoredCols 插入时需要忽略的列名 列名格式是Underscore,如created_at
      * @return sql
      * @return sql
+     *  插入单个参数(除了ignoredCols以外的参数)时,mapper写方法就行,实例见 UserMapper.insert
+     *  插入时填入了ignoredCols参数(比如不要id、startTime等自增、默认值字段),实例见PipelineHistoryMapper.insert
      */
      */
     public static String insert(Object obj,String... ignoredCols){
     public static String insert(Object obj,String... ignoredCols){
         Map<String, String> map;
         Map<String, String> map;

+ 6 - 0
web/src/main/java/seecoder/devcloud/web/model/po/pipeline/PipelineHistoryPO.java

@@ -1,6 +1,9 @@
 package seecoder.devcloud.web.model.po.pipeline;
 package seecoder.devcloud.web.model.po.pipeline;
 
 
+import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
 import lombok.Data;
+import lombok.NoArgsConstructor;
 
 
 import java.sql.Timestamp;
 import java.sql.Timestamp;
 
 
@@ -10,6 +13,9 @@ import java.sql.Timestamp;
  * @description:
  * @description:
  */
  */
 @Data
 @Data
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
 public class PipelineHistoryPO {
 public class PipelineHistoryPO {
 
 
     /**
     /**

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/model/po/project/BugListPO.java

@@ -27,7 +27,7 @@ public class BugListPO {
     private String description;
     private String description;
 
 
     /**
     /**
-     * 预计需要时间, 单位毫秒
+     * 预计需要时间
      */
      */
     private Long expectedTimeCost;
     private Long expectedTimeCost;
 
 

+ 3 - 1
web/src/main/java/seecoder/devcloud/web/model/vo/project/BugListUpdateBasicVO.java

@@ -23,5 +23,7 @@ public class BugListUpdateBasicVO {
     @ApiModelProperty("描述")
     @ApiModelProperty("描述")
     private String description;
     private String description;
     @ApiModelProperty("预计花销时间,单位毫秒")
     @ApiModelProperty("预计花销时间,单位毫秒")
-    private Long ExpectedTimeCost;
+    private Long expectedTimeCost;
+    @ApiModelProperty("负责人")
+    private String processor_id;
 }
 }

+ 9 - 1
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/DeploymentServiceImpl.java

@@ -18,6 +18,7 @@ import seecoder.devcloud.web.model.po.pipeline.PipelinePO;
 import seecoder.devcloud.web.model.po.project.ProjectPO;
 import seecoder.devcloud.web.model.po.project.ProjectPO;
 import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
 import seecoder.devcloud.web.model.vo.pipeline.DeploymentInfoVO;
 import seecoder.devcloud.web.service.pipeline.DeploymentService;
 import seecoder.devcloud.web.service.pipeline.DeploymentService;
+import seecoder.devcloud.web.service.user.UserService;
 
 
 import java.util.List;
 import java.util.List;
 import java.util.Map;
 import java.util.Map;
@@ -57,7 +58,7 @@ public class DeploymentServiceImpl implements DeploymentService {
         // 获取项目所关联的所有流水线
         // 获取项目所关联的所有流水线
         List<Integer> pipelineIds = pipelines.stream().map(PipelinePO::getId).collect(Collectors.toList());
         List<Integer> pipelineIds = pipelines.stream().map(PipelinePO::getId).collect(Collectors.toList());
         // 获取流水线历史
         // 获取流水线历史
-        List<PipelineHistoryPO> histories = pipelineHistoryMapper.selectRecentlyHistoryBy(pipelineIds);
+        List<PipelineHistoryPO> histories = pipelineHistoryMapper.selectPipelinesRecentlyHistory(pipelineIds);
         Map<Integer, PipelineHistoryPO> historyMap = histories.stream().collect(Collectors.toMap(PipelineHistoryPO::getPipelineId, x->x));
         Map<Integer, PipelineHistoryPO> historyMap = histories.stream().collect(Collectors.toMap(PipelineHistoryPO::getPipelineId, x->x));
         return pipelines.stream().map(x->{
         return pipelines.stream().map(x->{
             String accessUrl = x.getName()+"."+project.getName()+ properties.getK8s().getIngressHostSuffix();
             String accessUrl = x.getName()+"."+project.getName()+ properties.getK8s().getIngressHostSuffix();
@@ -86,6 +87,13 @@ public class DeploymentServiceImpl implements DeploymentService {
         //projectAuthentication(projectId);
         //projectAuthentication(projectId);
         PipelinePO pipelinePO = pipelineMapper.selectById(pipelineId);
         PipelinePO pipelinePO = pipelineMapper.selectById(pipelineId);
         ProjectPO projectPO = projectMapper.getProjectById(projectId);
         ProjectPO projectPO = projectMapper.getProjectById(projectId);
+        PipelineHistoryPO history = PipelineHistoryPO.builder()
+                .result("部署中")
+                .pipelineId(pipelinePO.getId())
+                .userId(UserService.loginUser().getId())
+                .details("")
+                .build();
+        pipelineHistoryMapper.insert(history,"id","startTime");
         try {
         try {
             Pipeline pipeline = PipelineFactory.init(pipelinePO.getConfigJson(), projectPO.getName(), pipelinePO.getName(), pipelineId, pipelinePO.getTemplateName());
             Pipeline pipeline = PipelineFactory.init(pipelinePO.getConfigJson(), projectPO.getName(), pipelinePO.getName(), pipelineId, pipelinePO.getTemplateName());
             //todo 异步记录结果
             //todo 异步记录结果

+ 1 - 1
web/src/main/java/seecoder/devcloud/web/service/impl/pipeline/PipelineServiceImpl.java

@@ -56,7 +56,7 @@ public class PipelineServiceImpl implements PipelineService {
         List<PipelinePO> pipelinePOS = pipelineMapper.selectByProjectId(projectId);
         List<PipelinePO> pipelinePOS = pipelineMapper.selectByProjectId(projectId);
         List<Integer> pipelineIds = pipelinePOS.stream().map(PipelinePO::getId).collect(Collectors.toList());
         List<Integer> pipelineIds = pipelinePOS.stream().map(PipelinePO::getId).collect(Collectors.toList());
         // 获取流水线历史
         // 获取流水线历史
-        List<PipelineHistoryPO> histories = pipelineHistoryMapper.selectRecentlyHistoryBy(pipelineIds);
+        List<PipelineHistoryPO> histories = pipelineHistoryMapper.selectPipelinesRecentlyHistory(pipelineIds);
         Map<Integer, PipelineHistoryPO> historyMap = histories.stream().collect(Collectors.toMap(PipelineHistoryPO::getPipelineId, x->x));
         Map<Integer, PipelineHistoryPO> historyMap = histories.stream().collect(Collectors.toMap(PipelineHistoryPO::getPipelineId, x->x));
         // 获取流水线历史中具体执行人信息
         // 获取流水线历史中具体执行人信息
         List<Integer> userIds = histories.stream().map(PipelineHistoryPO::getUserId).collect(Collectors.toList());
         List<Integer> userIds = histories.stream().map(PipelineHistoryPO::getUserId).collect(Collectors.toList());

+ 3 - 6
web/src/main/java/seecoder/devcloud/web/service/impl/project/BugListServiceImpl.java

@@ -1,5 +1,6 @@
 package seecoder.devcloud.web.service.impl.project;
 package seecoder.devcloud.web.service.impl.project;
 
 
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 import seecoder.devcloud.core.commit.CommitState;
 import seecoder.devcloud.core.commit.CommitState;
@@ -72,12 +73,8 @@ public class BugListServiceImpl implements BugListService {
 
 
     @Override
     @Override
     public void updateBasicInfo(BugListUpdateBasicVO vo) {
     public void updateBasicInfo(BugListUpdateBasicVO vo) {
-        BugListPO po = BugListPO.builder()
-                .priority(vo.getPriority())
-                .title(vo.getTitle())
-                .description(vo.getDescription())
-                .expectedTimeCost(vo.getExpectedTimeCost())
-                .build();
+        BugListPO po = BugListPO.builder().build();
+        BeanUtils.copyProperties(vo,po);
         bugListMapper.update(po);
         bugListMapper.update(po);
     }
     }
 
 

+ 0 - 12
web/src/main/resources/sql/deployment.sql

@@ -1,12 +0,0 @@
-create table if not exists devcloud.deployment
-(
-    id            int auto_increment
-        primary key,
-    name          varchar(23)                         not null,
-    deployed_time timestamp default CURRENT_TIMESTAMP not null,
-    access_url    varchar(127)                        not null,
-    pipeline_id   int                                 null,
-    constraint deployment_pipeline_id_fk
-        foreign key (pipeline_id) references devcloud.pipelinePO (id)
-);
-

+ 1 - 1
web/src/main/resources/sql/pipeline.sql

@@ -1,6 +1,6 @@
 create table if not exists devcloud.pipeline
 create table if not exists devcloud.pipeline
 (
 (
-    id            int         not null
+    id            int auto_increment
         primary key,
         primary key,
     project_id    int         null,
     project_id    int         null,
     name          varchar(47) null,
     name          varchar(47) null,

+ 4 - 2
web/src/main/resources/sql/pipeline_history.sql

@@ -1,6 +1,6 @@
 create table if not exists devcloud.pipeline_history
 create table if not exists devcloud.pipeline_history
 (
 (
-    id          int                                 not null
+    id          int auto_increment
         primary key,
         primary key,
     pipeline_id int                                 null,
     pipeline_id int                                 null,
     start_time  timestamp default CURRENT_TIMESTAMP not null,
     start_time  timestamp default CURRENT_TIMESTAMP not null,
@@ -8,6 +8,8 @@ create table if not exists devcloud.pipeline_history
     result      varchar(15)                         null,
     result      varchar(15)                         null,
     details     text                                null,
     details     text                                null,
     constraint pipeline_history_pipeline_id_fk
     constraint pipeline_history_pipeline_id_fk
-        foreign key (pipeline_id) references devcloud.pipelinePO (id)
+        foreign key (pipeline_id) references devcloud.pipeline (id),
+    constraint pipeline_history_user_id_fk
+        foreign key (user_id) references devcloud.user (id)
 );
 );
 
 

+ 51 - 0
web/src/test/java/seecoder/devcloud/web/dao/pipeline/PipelineHistoryMapperTest.java

@@ -0,0 +1,51 @@
+package seecoder.devcloud.web.dao.pipeline;
+
+import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.web.model.po.pipeline.PipelineHistoryPO;
+
+import java.util.Arrays;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/24
+ * @description:
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@MapperScan(basePackages = {"seecoder.devcloud.web.dao"})
+class PipelineHistoryMapperTest {
+
+    private final PipelineHistoryMapper historyMapper;
+
+    @Autowired
+    PipelineHistoryMapperTest(PipelineHistoryMapper historyMapper) {
+        this.historyMapper = historyMapper;
+    }
+
+    @Test
+    void insert(){
+        PipelineHistoryPO po = PipelineHistoryPO
+                .builder()
+                .pipelineId(7)
+                .details("leftright")
+                .result("down")
+                .userId(4)
+                .build();
+        historyMapper.insert(po,"id","startTime");
+    }
+
+    @Test
+    void selectByPipelineId() {
+        System.out.println(historyMapper.selectByPipelineId(4));
+    }
+
+    @Test
+    void selectPipelinesRecentlyHistory() {
+        System.out.println(historyMapper.selectPipelinesRecentlyHistory(Arrays.asList(4,7)));
+    }
+}

+ 3 - 3
web/src/test/java/seecoder/devcloud/web/dao/pipeline/PipelineMapperTest.java

@@ -30,9 +30,9 @@ class PipelineMapperTest {
     @Test
     @Test
     void insert() {
     void insert() {
         PipelinePO po = PipelinePO.builder()
         PipelinePO po = PipelinePO.builder()
-                .configJson("tettst")
-                .name("tttsd")
-                .projectId(2)
+                .configJson("newt")
+                .name("newd")
+                .projectId(1)
                 .templateName("SPRINGBOOT-JAVA8")
                 .templateName("SPRINGBOOT-JAVA8")
                 .build();
                 .build();
         pipelineMapper.insert(po, "id");
         pipelineMapper.insert(po, "id");

+ 64 - 0
web/src/test/java/seecoder/devcloud/web/dao/project/BugListMapperTest.java

@@ -0,0 +1,64 @@
+package seecoder.devcloud.web.dao.project;
+
+import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.web.model.enums.BugListStateEnum;
+import seecoder.devcloud.web.model.enums.PriorityEnum;
+import seecoder.devcloud.web.model.po.project.BugListPO;
+
+/**
+ * @author PuHong Weng
+ * @date 2021/3/24
+ * @description:
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@MapperScan(basePackages = {"seecoder.devcloud.web.dao"})
+class BugListMapperTest {
+
+    private final BugListMapper bugListMapper;
+
+    @Autowired
+    BugListMapperTest(BugListMapper bugListMapper) {
+        this.bugListMapper = bugListMapper;
+    }
+
+
+    @Test
+    void insert() {
+        BugListPO po = BugListPO.builder()
+                .title("大bug")
+                .description("全是错误")
+                .state(BugListStateEnum.CREATED)
+                .expectedTimeCost(1L)
+                .priority(PriorityEnum.HIGH)
+                .projectId(2)
+                .processorId(1)
+                .build();
+
+        bugListMapper.insert(po,"id","startTime","endTime");
+    }
+
+    @Test
+    void update() {
+        BugListPO po = BugListPO.builder()
+                .id(1)
+                .title("小bug")
+                .description("小错误")
+                .expectedTimeCost(10L)
+                .priority(PriorityEnum.MIDDLE)
+                .processorId(2)
+                .build();
+
+        bugListMapper.update(po);
+    }
+
+    @Test
+    void selectByProjectId() {
+        System.out.println(bugListMapper.selectByProjectId(1));
+    }
+}