feat: improve audit log aspect
This commit is contained in:
parent
919bd6de87
commit
92775dfd3b
|
@ -39,9 +39,10 @@ public class DocumentController {
|
||||||
private final ProjectService projectService;
|
private final ProjectService projectService;
|
||||||
|
|
||||||
@PostMapping(Routes.Document.SYNC_ONE)
|
@PostMapping(Routes.Document.SYNC_ONE)
|
||||||
@AuditLog(module = AuditLog.Modules.PROJECT, name = "文档同步", involvedProjectId = "#projectId")
|
@AuditLog(module = AuditLog.Modules.PROJECT, name = "创建同步任务", involvedProjectId = "#projectId",
|
||||||
@Operation(summary = "同步文档")
|
retrieveInvolvedGroupId = true)
|
||||||
public JsonData<Integer> sync(@PathVariable Integer projectId) {
|
@Operation(summary = "创建同步任务")
|
||||||
|
public JsonData<Integer> createSyncTask(@PathVariable Integer projectId) {
|
||||||
Integer userId = LoginUserContext.getLoginUserId();
|
Integer userId = LoginUserContext.getLoginUserId();
|
||||||
Optional<Integer> taskIdOpt = projectService.createSyncTask(projectId, userId, false);
|
Optional<Integer> taskIdOpt = projectService.createSyncTask(projectId, userId, false);
|
||||||
return JsonData.ok(taskIdOpt);
|
return JsonData.ok(taskIdOpt);
|
||||||
|
@ -67,6 +68,8 @@ public class DocumentController {
|
||||||
|
|
||||||
@GetMapping(Routes.Document.EXPORT)
|
@GetMapping(Routes.Document.EXPORT)
|
||||||
@Operation(summary = "导出文档")
|
@Operation(summary = "导出文档")
|
||||||
|
@AuditLog(module = AuditLog.Modules.PROJECT, name = "导出文档", involvedProjectId = "#projectId",
|
||||||
|
retrieveInvolvedGroupId = true)
|
||||||
public ResponseEntity<StreamingResponseBody> getDocumentFiles(@PathVariable Integer projectId,
|
public ResponseEntity<StreamingResponseBody> getDocumentFiles(@PathVariable Integer projectId,
|
||||||
@RequestParam(required = false)
|
@RequestParam(required = false)
|
||||||
Long version,
|
Long version,
|
||||||
|
|
|
@ -30,7 +30,8 @@ public class DocumentDescriptionController {
|
||||||
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)")
|
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)")
|
||||||
@AuditLog(module = AuditLog.Modules.PROJECT,
|
@AuditLog(module = AuditLog.Modules.PROJECT,
|
||||||
name = "更新描述",
|
name = "更新描述",
|
||||||
involvedProjectId = "#projectId")
|
involvedProjectId = "#projectId",
|
||||||
|
retrieveInvolvedGroupId = true)
|
||||||
@Operation(summary = "更新描述")
|
@Operation(summary = "更新描述")
|
||||||
public JsonData<Void> save(@PathVariable Integer groupId,
|
public JsonData<Void> save(@PathVariable Integer groupId,
|
||||||
@PathVariable Integer projectId,
|
@PathVariable Integer projectId,
|
||||||
|
|
|
@ -45,7 +45,8 @@ public class DocumentDiscussionController {
|
||||||
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId)")
|
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId)")
|
||||||
@AuditLog(module = AuditLog.Modules.PROJECT,
|
@AuditLog(module = AuditLog.Modules.PROJECT,
|
||||||
name = "删除评论",
|
name = "删除评论",
|
||||||
involvedProjectId = "#projectId")
|
involvedProjectId = "#projectId",
|
||||||
|
retrieveInvolvedGroupId = true)
|
||||||
@Operation(summary = "删除评论")
|
@Operation(summary = "删除评论")
|
||||||
public JsonData<Void> delete(@PathVariable Integer groupId,
|
public JsonData<Void> delete(@PathVariable Integer groupId,
|
||||||
@PathVariable Integer projectId,
|
@PathVariable Integer projectId,
|
||||||
|
@ -58,7 +59,8 @@ public class DocumentDiscussionController {
|
||||||
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)")
|
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)")
|
||||||
@AuditLog(module = AuditLog.Modules.PROJECT,
|
@AuditLog(module = AuditLog.Modules.PROJECT,
|
||||||
name = "新增评论",
|
name = "新增评论",
|
||||||
involvedProjectId = "#projectId")
|
involvedProjectId = "#projectId",
|
||||||
|
retrieveInvolvedGroupId = true)
|
||||||
@Operation(summary = "新增评论")
|
@Operation(summary = "新增评论")
|
||||||
public JsonData<Void> create(@PathVariable Integer groupId,
|
public JsonData<Void> create(@PathVariable Integer groupId,
|
||||||
@PathVariable Integer projectId,
|
@PathVariable Integer projectId,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package com.databasir.api;
|
package com.databasir.api;
|
||||||
|
|
||||||
import com.databasir.common.JsonData;
|
import com.databasir.common.JsonData;
|
||||||
|
import com.databasir.core.domain.log.annotation.AuditLog;
|
||||||
import com.databasir.core.domain.mock.MockDataService;
|
import com.databasir.core.domain.mock.MockDataService;
|
||||||
import com.databasir.core.domain.mock.data.ColumnMockRuleSaveRequest;
|
import com.databasir.core.domain.mock.data.ColumnMockRuleSaveRequest;
|
||||||
import com.databasir.core.domain.mock.data.MockDataGenerateCondition;
|
import com.databasir.core.domain.mock.data.MockDataGenerateCondition;
|
||||||
|
@ -45,6 +46,9 @@ public class MockDataController {
|
||||||
@PostMapping(Routes.MockData.SAVE_MOCK_RULE)
|
@PostMapping(Routes.MockData.SAVE_MOCK_RULE)
|
||||||
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)")
|
@PreAuthorize("hasAnyAuthority('SYS_OWNER', 'GROUP_OWNER?groupId='+#groupId, 'GROUP_MEMBER?groupId='+#groupId)")
|
||||||
@Operation(summary = "保存 Mock Rule")
|
@Operation(summary = "保存 Mock Rule")
|
||||||
|
@AuditLog(module = AuditLog.Modules.PROJECT, name = "保存 Mock Rule",
|
||||||
|
involvedProjectId = "#projectId",
|
||||||
|
involvedGroupId = "#groupId")
|
||||||
public JsonData<Void> saveMockRules(@PathVariable Integer groupId,
|
public JsonData<Void> saveMockRules(@PathVariable Integer groupId,
|
||||||
@PathVariable Integer projectId,
|
@PathVariable Integer projectId,
|
||||||
@PathVariable Integer tableId,
|
@PathVariable Integer tableId,
|
||||||
|
|
|
@ -107,6 +107,8 @@ public class ProjectController {
|
||||||
|
|
||||||
@PatchMapping(Routes.GroupProject.CANCEL_MANUAL_TASK)
|
@PatchMapping(Routes.GroupProject.CANCEL_MANUAL_TASK)
|
||||||
@Operation(summary = "取消同步任务")
|
@Operation(summary = "取消同步任务")
|
||||||
|
@AuditLog(module = AuditLog.Modules.PROJECT, name = "取消同步任务", involvedProjectId = "#projectId",
|
||||||
|
retrieveInvolvedGroupId = true)
|
||||||
public JsonData<Void> cancelTask(@PathVariable Integer projectId,
|
public JsonData<Void> cancelTask(@PathVariable Integer projectId,
|
||||||
@PathVariable Integer taskId) {
|
@PathVariable Integer taskId) {
|
||||||
projectService.cancelTask(projectId, taskId);
|
projectService.cancelTask(projectId, taskId);
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.databasir.api;
|
||||||
|
|
||||||
import com.databasir.api.config.security.DatabasirUserDetails;
|
import com.databasir.api.config.security.DatabasirUserDetails;
|
||||||
import com.databasir.common.JsonData;
|
import com.databasir.common.JsonData;
|
||||||
|
import com.databasir.core.domain.log.annotation.AuditLog;
|
||||||
import com.databasir.core.domain.user.data.FavoriteProjectPageCondition;
|
import com.databasir.core.domain.user.data.FavoriteProjectPageCondition;
|
||||||
import com.databasir.core.domain.user.data.FavoriteProjectPageResponse;
|
import com.databasir.core.domain.user.data.FavoriteProjectPageResponse;
|
||||||
import com.databasir.core.domain.user.service.UserProjectService;
|
import com.databasir.core.domain.user.service.UserProjectService;
|
||||||
|
@ -39,6 +40,9 @@ public class UserProjectController {
|
||||||
|
|
||||||
@PostMapping(Routes.UserProject.ADD)
|
@PostMapping(Routes.UserProject.ADD)
|
||||||
@Operation(summary = "添加用户关注项目")
|
@Operation(summary = "添加用户关注项目")
|
||||||
|
@AuditLog(module = AuditLog.Modules.PROJECT, name = "关注项目",
|
||||||
|
involvedProjectId = "#projectId",
|
||||||
|
retrieveInvolvedGroupId = true)
|
||||||
public JsonData<Void> addFavorite(@PathVariable Integer projectId) {
|
public JsonData<Void> addFavorite(@PathVariable Integer projectId) {
|
||||||
DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext()
|
DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext()
|
||||||
.getAuthentication()
|
.getAuthentication()
|
||||||
|
@ -50,6 +54,9 @@ public class UserProjectController {
|
||||||
|
|
||||||
@DeleteMapping(Routes.UserProject.REMOVE)
|
@DeleteMapping(Routes.UserProject.REMOVE)
|
||||||
@Operation(summary = "删除用户关注项目")
|
@Operation(summary = "删除用户关注项目")
|
||||||
|
@AuditLog(module = AuditLog.Modules.PROJECT, name = "取消关注",
|
||||||
|
involvedProjectId = "#projectId",
|
||||||
|
retrieveInvolvedGroupId = true)
|
||||||
public JsonData<Void> removeFavorite(@PathVariable Integer projectId) {
|
public JsonData<Void> removeFavorite(@PathVariable Integer projectId) {
|
||||||
DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext()
|
DatabasirUserDetails user = (DatabasirUserDetails) SecurityContextHolder.getContext()
|
||||||
.getAuthentication()
|
.getAuthentication()
|
||||||
|
|
|
@ -5,6 +5,8 @@ import com.databasir.common.JsonData;
|
||||||
import com.databasir.core.domain.log.annotation.AuditLog;
|
import com.databasir.core.domain.log.annotation.AuditLog;
|
||||||
import com.databasir.core.domain.log.data.OperationLogRequest;
|
import com.databasir.core.domain.log.data.OperationLogRequest;
|
||||||
import com.databasir.core.domain.log.service.OperationLogService;
|
import com.databasir.core.domain.log.service.OperationLogService;
|
||||||
|
import com.databasir.dao.impl.ProjectDao;
|
||||||
|
import com.databasir.dao.tables.pojos.ProjectPojo;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
@ -33,13 +35,19 @@ public class OperationLogAspect {
|
||||||
|
|
||||||
private final OperationLogService operationLogService;
|
private final OperationLogService operationLogService;
|
||||||
|
|
||||||
|
private final ProjectDao projectDao;
|
||||||
|
|
||||||
private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
private SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
|
||||||
|
|
||||||
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||||
|
|
||||||
@AfterReturning(value = "@annotation(operation)", returning = "returnValue")
|
@AfterReturning(value = "@annotation(operation)", returning = "returnValue")
|
||||||
public void log(JoinPoint joinPoint, Object returnValue, AuditLog operation) {
|
public void log(JoinPoint joinPoint, Object returnValue, AuditLog operation) {
|
||||||
|
if (returnValue instanceof JsonData) {
|
||||||
saveLog(operation, joinPoint, (JsonData<Object>) returnValue);
|
saveLog(operation, joinPoint, (JsonData<Object>) returnValue);
|
||||||
|
} else {
|
||||||
|
saveLog(operation, joinPoint, JsonData.ok());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterThrowing(value = "@annotation(operation)", throwing = "ex")
|
@AfterThrowing(value = "@annotation(operation)", throwing = "ex")
|
||||||
|
@ -62,6 +70,14 @@ public class OperationLogAspect {
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
Integer involvedUserId = getValueBySPEL(method, arguments, operation.involvedUserId(), Integer.class)
|
Integer involvedUserId = getValueBySPEL(method, arguments, operation.involvedUserId(), Integer.class)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
|
// auto fill involvedProjectId
|
||||||
|
if (involvedGroupId == null
|
||||||
|
&& operation.retrieveInvolvedGroupId()
|
||||||
|
&& involvedProjectId != null) {
|
||||||
|
involvedGroupId = projectDao.selectOptionalById(involvedProjectId)
|
||||||
|
.map(ProjectPojo::getGroupId)
|
||||||
|
.orElse(null);
|
||||||
|
}
|
||||||
int userId = userId();
|
int userId = userId();
|
||||||
String username = principal.getUserPojo().getUsername();
|
String username = principal.getUserPojo().getUsername();
|
||||||
String nickname = principal.getUserPojo().getNickname();
|
String nickname = principal.getUserPojo().getNickname();
|
||||||
|
|
|
@ -5,8 +5,10 @@ import com.databasir.core.domain.document.service.DocumentService;
|
||||||
import com.databasir.core.domain.log.data.OperationLogRequest;
|
import com.databasir.core.domain.log.data.OperationLogRequest;
|
||||||
import com.databasir.core.domain.log.service.OperationLogService;
|
import com.databasir.core.domain.log.service.OperationLogService;
|
||||||
import com.databasir.dao.enums.ProjectSyncTaskStatus;
|
import com.databasir.dao.enums.ProjectSyncTaskStatus;
|
||||||
|
import com.databasir.dao.impl.ProjectDao;
|
||||||
import com.databasir.dao.impl.ProjectSyncTaskDao;
|
import com.databasir.dao.impl.ProjectSyncTaskDao;
|
||||||
import com.databasir.dao.impl.UserDao;
|
import com.databasir.dao.impl.UserDao;
|
||||||
|
import com.databasir.dao.tables.pojos.ProjectSyncTaskPojo;
|
||||||
import com.databasir.dao.tables.pojos.UserPojo;
|
import com.databasir.dao.tables.pojos.UserPojo;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
@ -14,7 +16,10 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@ -29,6 +34,8 @@ public class ProjectSyncTaskScheduler {
|
||||||
|
|
||||||
private final ProjectSyncTaskDao projectSyncTaskDao;
|
private final ProjectSyncTaskDao projectSyncTaskDao;
|
||||||
|
|
||||||
|
private final ProjectDao projectDao;
|
||||||
|
|
||||||
private final ThreadPoolTaskExecutor projectSyncTaskThreadPoolTaskExecutor;
|
private final ThreadPoolTaskExecutor projectSyncTaskThreadPoolTaskExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,26 +44,33 @@ public class ProjectSyncTaskScheduler {
|
||||||
@Scheduled(fixedRate = 5000L)
|
@Scheduled(fixedRate = 5000L)
|
||||||
public void startSyncTask() {
|
public void startSyncTask() {
|
||||||
final int size = 10;
|
final int size = 10;
|
||||||
projectSyncTaskDao.listNewTasks(size).forEach(task -> {
|
List<ProjectSyncTaskPojo> tasks = projectSyncTaskDao.listNewTasks(size);
|
||||||
|
List<Integer> projectIds = tasks.stream()
|
||||||
|
.map(ProjectSyncTaskPojo::getProjectId)
|
||||||
|
.distinct()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Map<Integer, Integer> groupIdAndProjectIdMap = projectDao.selectGroupIdsByProjectIdIn(projectIds);
|
||||||
|
tasks.forEach(task -> {
|
||||||
projectSyncTaskThreadPoolTaskExecutor.execute(() -> {
|
projectSyncTaskThreadPoolTaskExecutor.execute(() -> {
|
||||||
Integer taskId = task.getId();
|
Integer taskId = task.getId();
|
||||||
Integer projectId = task.getProjectId();
|
Integer projectId = task.getProjectId();
|
||||||
|
Integer groupId = groupIdAndProjectIdMap.get(projectId);
|
||||||
Integer userId = task.getUserId();
|
Integer userId = task.getUserId();
|
||||||
sync(taskId, projectId, userId);
|
sync(taskId, groupId, projectId, userId);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sync(Integer taskId, Integer projectId, Integer userId) {
|
private void sync(Integer taskId, Integer groupId, Integer projectId, Integer userId) {
|
||||||
try {
|
try {
|
||||||
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.RUNNING, "running");
|
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.RUNNING, "running");
|
||||||
documentService.syncByProjectId(projectId);
|
documentService.syncByProjectId(projectId);
|
||||||
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.FINISHED, "ok");
|
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.FINISHED, "ok");
|
||||||
saveOperationLog(projectId, userId, null);
|
saveOperationLog(groupId, projectId, userId, null);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
String result = Objects.requireNonNullElse(e.getMessage(), "unknown");
|
String result = Objects.requireNonNullElse(e.getMessage(), "unknown");
|
||||||
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.FAILED, result);
|
updateSyncTaskStatus(taskId, ProjectSyncTaskStatus.FAILED, result);
|
||||||
saveOperationLog(projectId, userId, e);
|
saveOperationLog(groupId, projectId, userId, e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,19 +79,19 @@ public class ProjectSyncTaskScheduler {
|
||||||
projectSyncTaskDao.updateStatusAndResultById(taskId, status, result);
|
projectSyncTaskDao.updateStatusAndResultById(taskId, status, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveOperationLog(Integer projectId, Integer userId, Exception ex) {
|
private void saveOperationLog(Integer groupId, Integer projectId, Integer userId, Exception ex) {
|
||||||
String operatorNickName;
|
String operatorNickName;
|
||||||
String operatorUsername;
|
String operatorUsername;
|
||||||
String operationName;
|
String operationName;
|
||||||
if (Objects.equals(-1, userId)) {
|
if (Objects.equals(-1, userId)) {
|
||||||
operatorNickName = "system";
|
operatorNickName = "system";
|
||||||
operatorUsername = "system";
|
operatorUsername = "system";
|
||||||
operationName = "文档定时同步";
|
operationName = "定时同步";
|
||||||
} else {
|
} else {
|
||||||
UserPojo user = userDao.selectById(userId);
|
UserPojo user = userDao.selectById(userId);
|
||||||
operatorNickName = user.getNickname();
|
operatorNickName = user.getNickname();
|
||||||
operatorUsername = user.getUsername();
|
operatorUsername = user.getUsername();
|
||||||
operationName = "文档手动同步";
|
operationName = "手动同步";
|
||||||
}
|
}
|
||||||
JsonData response;
|
JsonData response;
|
||||||
if (ex == null) {
|
if (ex == null) {
|
||||||
|
@ -95,6 +109,7 @@ public class ProjectSyncTaskScheduler {
|
||||||
.operationResponse(response)
|
.operationResponse(response)
|
||||||
.isSuccess(ex == null)
|
.isSuccess(ex == null)
|
||||||
.involvedProjectId(projectId)
|
.involvedProjectId(projectId)
|
||||||
|
.involvedGroupId(groupId)
|
||||||
.build();
|
.build();
|
||||||
operationLogService.save(operationLog);
|
operationLogService.save(operationLog);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,8 @@ public @interface AuditLog {
|
||||||
*/
|
*/
|
||||||
String involvedUserId() default "N/A";
|
String involvedUserId() default "N/A";
|
||||||
|
|
||||||
|
boolean retrieveInvolvedGroupId() default false;
|
||||||
|
|
||||||
interface Modules {
|
interface Modules {
|
||||||
String UNKNOWN = "UNKNOWN";
|
String UNKNOWN = "UNKNOWN";
|
||||||
String PROJECT = "project";
|
String PROJECT = "project";
|
||||||
|
|
|
@ -115,4 +115,15 @@ public class ProjectDao extends BaseDao<ProjectPojo> {
|
||||||
.groupBy(DATA_SOURCE.DATABASE_TYPE)
|
.groupBy(DATA_SOURCE.DATABASE_TYPE)
|
||||||
.fetchMap(DATA_SOURCE.DATABASE_TYPE, DSL.count(DATA_SOURCE));
|
.fetchMap(DATA_SOURCE.DATABASE_TYPE, DSL.count(DATA_SOURCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<Integer, Integer> selectGroupIdsByProjectIdIn(List<Integer> projectIds) {
|
||||||
|
if (projectIds == null || projectIds.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
return getDslContext()
|
||||||
|
.select(PROJECT.ID, PROJECT.GROUP_ID)
|
||||||
|
.from(PROJECT)
|
||||||
|
.where(PROJECT.ID.in(projectIds))
|
||||||
|
.fetchMap(PROJECT.ID, PROJECT.GROUP_ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue