1
0

feat(web): 使用统一的超类和子图查询来优化查询性能

This commit is contained in:
2024-11-21 19:17:14 +08:00
parent ccbefb9bdf
commit c51228bf42
15 changed files with 300 additions and 80 deletions

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.entity;
package com.eshore.gringotts.web.domain.base.entity;
import java.time.LocalDateTime;
import javax.persistence.EntityListeners;

View File

@@ -1,22 +1,13 @@
package com.eshore.gringotts.web.domain.entity;
package com.eshore.gringotts.web.domain.base.entity;
import com.eshore.gringotts.web.domain.user.entity.User;
import java.time.LocalDateTime;
import javax.persistence.ConstraintMode;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.MappedSuperclass;
import javax.persistence.OneToOne;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.GenericGenerator;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
/**

View File

@@ -1,4 +1,4 @@
package com.eshore.gringotts.web.domain.entity;
package com.eshore.gringotts.web.domain.base.entity;
import com.eshore.gringotts.web.domain.user.entity.User;
import java.time.LocalDateTime;

View File

@@ -0,0 +1,25 @@
package com.eshore.gringotts.web.domain.base.service;
import cn.hutool.core.util.ObjectUtil;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import org.eclipse.collections.api.factory.Lists;
import org.eclipse.collections.api.list.ImmutableList;
/**
* @author lanyuanxiaoyao
* @date 2024-11-21
*/
public abstract class SimpleService<E, ID> {
protected abstract SimpleRepository<E, ID> repository();
public ImmutableList<E> list() {
return Lists.immutable.ofAll(repository().findAll());
}
public E detail(ID id) {
if (ObjectUtil.isNull(id)) {
return null;
}
return repository().findById(id).orElse(null);
}
}

View File

@@ -1,6 +1,10 @@
package com.eshore.gringotts.web.domain.resource.controller;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ObjectUtil;
import com.eshore.gringotts.web.configuration.amis.AmisListResponse;
import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.resource.entity.DataResource;
import com.eshore.gringotts.web.domain.resource.entity.format.CsvResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.format.JsonLineResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.format.JsonResourceFormat;
@@ -14,13 +18,19 @@ import com.eshore.gringotts.web.domain.resource.entity.type.FtpResourceType;
import com.eshore.gringotts.web.domain.resource.entity.type.HDFSResourceType;
import com.eshore.gringotts.web.domain.resource.entity.type.ResourceType;
import com.eshore.gringotts.web.domain.resource.service.DataResourceService;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import com.eshore.gringotts.web.domain.upload.service.DataFileService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.LocalDateTime;
import java.util.Map;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -32,90 +42,199 @@ import org.springframework.web.bind.annotation.RestController;
* @author lanyuanxiaoyao
* @date 2024-11-20
*/
@Slf4j
@RestController
@RequestMapping("/data_resource")
public class DataResourceController {
private static final Logger logger = LoggerFactory.getLogger(DataResourceController.class);
private final ObjectMapper mapper;
private final DataResourceService dataResourceService;
private final DataFileService dataFileService;
public DataResourceController(Jackson2ObjectMapperBuilder builder, DataResourceService dataResourceService) {
public DataResourceController(Jackson2ObjectMapperBuilder builder, DataResourceService dataResourceService, DataFileService dataFileService) {
this.mapper = builder.build();
this.dataResourceService = dataResourceService;
this.dataFileService = dataFileService;
}
@PostMapping("/create")
public void create(@RequestBody CreateRequest request) throws JsonProcessingException {
logger.info("Create request: {}", request);
log.info("Create request: {}", request);
ResourceType type = null;
switch (request.resourceType) {
case "api":
case API:
type = new ApiResourceType(request.apiUrl, request.apiUsername, request.apiPassword);
break;
case "file":
type = new FileResourceType(request.filePath);
case FILE:
DataFile dataFile = dataFileService.detail(request.fileId);
log.info("{}", dataFile);
type = new FileResourceType(dataFile);
break;
case "database":
case DATABASE:
type = new DatabaseResourceType(
request.databaseJdbc,
request.databaseUsername,
request.databasePassword,
EnumUtil.fromString(DatabaseResourceType.Type.class, request.databaseType)
EnumUtil.fromString(DatabaseResourceType.DatabaseType.class, request.databaseType)
);
break;
case "hdfs":
type = new HDFSResourceType(request.coreSiteFile, request.hdfsSiteFile);
case HDFS:
type = new HDFSResourceType(dataFileService.detail(request.coreSiteFileId), dataFileService.detail(request.hdfsSiteFileId));
break;
case "ftp":
case FTP:
type = new FtpResourceType(request.ftpUrl, request.ftpUsername, request.ftpPassword, request.ftpPath, request.ftpRegexFilter);
break;
}
ResourceFormat format = null;
switch (request.formatType) {
case "NONE":
case NONE:
format = new NoneResourceFormat();
break;
case "LINE":
case LINE:
format = new LineResourceFormat();
break;
case "JSON":
case JSON:
format = new JsonResourceFormat(mapper.writeValueAsString(request.jsonSchema));
break;
case "JSON_LINE":
case JSON_LINE:
format = new JsonLineResourceFormat(mapper.writeValueAsString(request.jsonLineSchema));
break;
case "CSV":
case CSV:
format = new CsvResourceFormat(mapper.writeValueAsString(request.csvSchema));
break;
}
dataResourceService.create(request.name, request.description, format, type);
dataResourceService.create(request.name, request.description, format, type, dataFileService.detail(request.exampleFileId));
}
@PostMapping("/list")
public AmisListResponse list() {
return AmisResponse.responseListData(dataResourceService.list().collect(DataResourceListItem::new));
}
@GetMapping("/detail/{id}")
public AmisResponse<DataResourceDetail> detail(@PathVariable Long id) throws JsonProcessingException {
return AmisResponse.responseSuccess(new DataResourceDetail(mapper, dataResourceService.detail(id)));
}
@Data
public static final class CreateRequest {
public static class CreateRequest {
protected String name;
protected String description;
protected ResourceType.Type resourceType;
protected String apiUrl;
protected String apiUsername;
protected String apiPassword;
protected String fileId;
protected String databaseType;
protected String databaseJdbc;
protected String databaseUsername;
protected String databasePassword;
protected String coreSiteFileId;
protected String hdfsSiteFileId;
protected String ftpUrl;
protected String ftpUsername;
protected String ftpPassword;
protected String ftpPath;
protected String ftpRegexFilter;
protected ResourceFormat.Type formatType;
protected Map<?, ?> jsonSchema;
protected Map<?, ?> jsonLineSchema;
protected Map<?, ?> csvSchema;
protected String exampleFileId;
}
@Data
public static final class DataResourceListItem {
private Long id;
private String name;
private String description;
private String resourceType;
private String apiUrl;
private String apiUsername;
private String apiPassword;
private String filePath;
private String databaseType;
private String databaseJdbc;
private String databaseUsername;
private String databasePassword;
private String coreSiteFile;
private String hdfsSiteFile;
private String ftpUrl;
private String ftpUsername;
private String ftpPassword;
private String ftpPath;
private String ftpRegexFilter;
private String formatType;
private Map<?, ?> jsonSchema;
private Map<?, ?> jsonLineSchema;
private Map<?, ?> csvSchema;
private String example;
private String type;
private String format;
private String createdUser;
private LocalDateTime createdTime;
public DataResourceListItem(DataResource dataResource) {
this.id = dataResource.getId();
this.name = dataResource.getName();
this.description = dataResource.getDescription();
this.type = dataResource.getType().getResourceType().name();
this.format = dataResource.getFormat().getFormatType().name();
this.createdUser = dataResource.getCreatedUser().getUsername();
this.createdTime = dataResource.getCreatedTime();
}
}
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public static final class DataResourceDetail extends CreateRequest {
private LocalDateTime createdTime;
private String createdUsername;
private LocalDateTime modifiedTime;
private String modifiedUsername;
public DataResourceDetail(ObjectMapper mapper, DataResource dataResource) throws JsonProcessingException {
log.info("DataResourceDetail: {}", dataResource);
this.name = dataResource.getName();
this.description = dataResource.getDescription();
this.resourceType = dataResource.getType().getResourceType();
switch (dataResource.getType().getResourceType()) {
case API:
ApiResourceType apiType = (ApiResourceType) dataResource.getType();
this.apiUrl = apiType.getUrl();
this.apiUsername = apiType.getUsername();
this.apiPassword = apiType.getPassword();
break;
case FILE:
FileResourceType fileType = (FileResourceType) dataResource.getType();
this.fileId = fileType.getFile().getFilename();
break;
case DATABASE:
DatabaseResourceType databaseType = (DatabaseResourceType) dataResource.getType();
this.databaseType = databaseType.getDatabaseType().name();
this.databaseJdbc = databaseType.getJdbc();
this.databaseUsername = databaseType.getUsername();
this.databasePassword = databaseType.getPassword();
break;
case HDFS:
HDFSResourceType hdfsType = (HDFSResourceType) dataResource.getType();
this.coreSiteFileId = hdfsType.getCoreSite().getFilename();
this.hdfsSiteFileId = hdfsType.getHdfsSite().getFilename();
break;
case FTP:
FtpResourceType ftpType = (FtpResourceType) dataResource.getType();
this.ftpUrl = ftpType.getUrl();
this.ftpUsername = ftpType.getUsername();
this.ftpPassword = ftpType.getPassword();
this.ftpPath = ftpType.getPath();
this.ftpRegexFilter = ftpType.getRegexFilter();
break;
}
this.formatType = dataResource.getFormat().getFormatType();
switch (dataResource.getFormat().getFormatType()) {
case NONE:
case LINE:
break;
case JSON:
JsonResourceFormat jsonFormat = (JsonResourceFormat) dataResource.getFormat();
this.jsonSchema = mapper.readValue(jsonFormat.getSchema(), Map.class);
break;
case JSON_LINE:
JsonLineResourceFormat jsonLineFormat = (JsonLineResourceFormat) dataResource.getFormat();
this.jsonLineSchema = mapper.readValue(jsonLineFormat.getSchema(), Map.class);
break;
case CSV:
CsvResourceFormat csvFormat = (CsvResourceFormat) dataResource.getFormat();
this.jsonLineSchema = mapper.readValue(csvFormat.getSchema(), Map.class);
break;
}
if (ObjectUtil.isNotNull(dataResource.getExample())) {
this.exampleFileId = dataResource.getExample().getFilename();
}
this.createdUsername = dataResource.getCreatedUser().getUsername();
this.createdTime = dataResource.getCreatedTime();
this.modifiedUsername = dataResource.getModifiedUser().getUsername();
this.modifiedTime = dataResource.getModifiedTime();
}
}
}

View File

@@ -13,6 +13,8 @@ import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Getter;
@@ -28,6 +30,18 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@EntityListeners(AuditingEntityListener.class)
@DynamicUpdate
@Table(name = Constants.TABLE_PREFIX + "data_resource")
@NamedEntityGraph(name = "data_resource.list", attributeNodes = {
@NamedAttributeNode(value = "type"),
@NamedAttributeNode(value = "format"),
@NamedAttributeNode(value = "createdUser"),
})
@NamedEntityGraph(name = "data_resource.detail", attributeNodes = {
@NamedAttributeNode(value = "type"),
@NamedAttributeNode(value = "format"),
@NamedAttributeNode(value = "example"),
@NamedAttributeNode(value = "createdUser"),
@NamedAttributeNode(value = "modifiedUser"),
})
public class DataResource extends SimpleEntity {
@Column(nullable = false)
private String name;

View File

@@ -4,6 +4,11 @@ import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -18,6 +23,9 @@ import lombok.ToString;
@NoArgsConstructor
@Entity
@Table(name = Constants.TABLE_PREFIX + "resource_type_file")
@NamedEntityGraph(name = "file_resource_type.detail", attributeNodes = {
@NamedAttributeNode(value = "file")
})
public class FileResourceType extends ResourceType {
@OneToOne
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))

View File

@@ -4,6 +4,11 @@ import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import javax.persistence.ConstraintMode;
import javax.persistence.Entity;
import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -18,6 +23,10 @@ import lombok.ToString;
@NoArgsConstructor
@Entity
@Table(name = Constants.TABLE_PREFIX + "resource_type_hdfs")
@NamedEntityGraph(name = "hdfs_resource_type.detail", attributeNodes = {
@NamedAttributeNode(value = "coreSite"),
@NamedAttributeNode(value = "hdfsSite"),
})
public class HDFSResourceType extends ResourceType {
@OneToOne
@JoinColumn(nullable = false, foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))

View File

@@ -2,8 +2,19 @@ package com.eshore.gringotts.web.domain.resource.repository;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.resource.entity.DataResource;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.stereotype.Repository;
@SuppressWarnings("NullableProblems")
@Repository
public interface DataResourceRepository extends SimpleRepository<DataResource, Long> {
@Override
@EntityGraph(value = "data_resource.list", type = EntityGraph.EntityGraphType.FETCH)
List<DataResource> findAll();
@Override
@EntityGraph(value = "data_resource.detail", type = EntityGraph.EntityGraphType.FETCH)
Optional<DataResource> findById(Long id);
}

View File

@@ -1,16 +1,18 @@
package com.eshore.gringotts.web.domain.resource.service;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.base.service.SimpleService;
import com.eshore.gringotts.web.domain.resource.entity.DataResource;
import com.eshore.gringotts.web.domain.resource.entity.format.ResourceFormat;
import com.eshore.gringotts.web.domain.resource.entity.type.ResourceType;
import com.eshore.gringotts.web.domain.resource.repository.DataResourceRepository;
import com.eshore.gringotts.web.domain.resource.repository.ResourceFormatRepository;
import com.eshore.gringotts.web.domain.resource.repository.ResourceTypeRepository;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import com.eshore.gringotts.web.domain.user.entity.User;
import com.eshore.gringotts.web.domain.user.service.UserService;
import javax.transaction.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
@@ -18,10 +20,9 @@ import org.springframework.stereotype.Service;
*
* @author lanyuanxiaoyao
*/
@Slf4j
@Service
public class DataResourceService {
private static final Logger log = LoggerFactory.getLogger(DataResourceService.class);
public class DataResourceService extends SimpleService<DataResource, Long> {
private final DataResourceRepository dataResourceRepository;
private final ResourceTypeRepository resourceTypeRepository;
private final ResourceFormatRepository resourceFormatRepository;
@@ -34,15 +35,22 @@ public class DataResourceService {
this.userService = userService;
}
@Override
protected SimpleRepository<DataResource, Long> repository() {
return dataResourceRepository;
}
@Transactional
public void create(String name, String description, ResourceFormat format, ResourceType type) {
public void create(String name, String description, ResourceFormat format, ResourceType type, DataFile example) {
resourceFormatRepository.save(format);
log.info("{}", type);
resourceTypeRepository.save(type);
DataResource resource = new DataResource();
resource.setName(name);
resource.setDescription(description);
resource.setFormat(format);
resource.setType(type);
resource.setExample(example);
User user = userService.currentLoginUser();
resource.setCreatedUser(user);
resource.setModifiedUser(user);

View File

@@ -5,7 +5,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.eshore.gringotts.web.configuration.UploadConfiguration;
import com.eshore.gringotts.web.configuration.amis.AmisResponse;
import com.eshore.gringotts.web.domain.upload.service.UploadService;
import com.eshore.gringotts.web.domain.upload.service.DataFileService;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -37,13 +37,13 @@ import org.springframework.web.multipart.MultipartFile;
public class UploadController {
private static final Logger logger = LoggerFactory.getLogger(UploadController.class);
private final UploadService uploadService;
private final DataFileService dataFileService;
private final String uploadFolderPath;
private final String cacheFolderPath;
private final String sliceFolderPath;
public UploadController(UploadConfiguration uploadConfiguration, UploadService uploadService) {
this.uploadService = uploadService;
public UploadController(UploadConfiguration uploadConfiguration, DataFileService dataFileService) {
this.dataFileService = dataFileService;
this.uploadFolderPath = uploadConfiguration.getUploadPath();
this.cacheFolderPath = StrUtil.format("{}/cache", uploadFolderPath);
@@ -53,7 +53,7 @@ public class UploadController {
@PostMapping("/start")
public AmisResponse<StartResponse> start(@RequestBody StartRequest request) {
logger.info("Request: {}", request);
Long id = uploadService.initialDataFile(request.filename);
Long id = dataFileService.initialDataFile(request.filename);
return AmisResponse.responseSuccess(new StartResponse(id.toString()));
}
@@ -68,7 +68,6 @@ public class UploadController {
@RequestParam("file")
MultipartFile file
) throws IOException {
logger.info("UploadId: {}, sequence: {}, size: {}, file: {}", uploadId, sequence, size, file.getName());
byte[] bytes = file.getBytes();
String md5 = SecureUtil.md5(new ByteArrayInputStream(bytes));
String targetFilename = StrUtil.format("{}-{}", sequence, md5);
@@ -84,7 +83,6 @@ public class UploadController {
@PostMapping("finish")
public AmisResponse<FinishResponse> finish(@RequestBody FinishRequest request) {
logger.info("Request: {}", request);
if (request.partList.anySatisfy(part -> !FileUtil.exist(sliceFilePath(request.uploadId, part.eTag)))) {
throw new RuntimeException("文件校验失败,请重新上传");
}
@@ -104,9 +102,12 @@ public class UploadController {
}
}
}
File targetFile = new File(StrUtil.format("{}/{}", uploadFolderPath, request.uploadId));
String md5 = SecureUtil.md5(cacheFile);
File targetFile = new File(StrUtil.format("{}/{}", uploadFolderPath, md5));
if (!targetFile.exists()) {
FileUtil.move(cacheFile, targetFile, true);
uploadService.updateDataFile(request.uploadId, FileUtil.getAbsolutePath(targetFile), FileUtil.size(targetFile), SecureUtil.md5(targetFile));
}
dataFileService.updateDataFile(request.uploadId, FileUtil.getAbsolutePath(targetFile), FileUtil.size(targetFile), SecureUtil.md5(targetFile));
return AmisResponse.responseSuccess(new FinishResponse(request.uploadId.toString()));
} else {
throw new RuntimeException("合并文件失败");
@@ -114,6 +115,7 @@ public class UploadController {
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
} finally {
FileUtil.del(StrUtil.format("{}/{}", cacheFolderPath, request.uploadId));
FileUtil.del(StrUtil.format("{}/{}", sliceFolderPath, request.uploadId));
}
}

View File

@@ -1,6 +1,6 @@
package com.eshore.gringotts.web.domain.upload.entity;
import com.eshore.gringotts.web.domain.entity.SimpleEntity;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;
import javax.persistence.Entity;
import lombok.Getter;
import lombok.Setter;

View File

@@ -1,5 +1,7 @@
package com.eshore.gringotts.web.domain.upload.service;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.base.service.SimpleService;
import com.eshore.gringotts.web.domain.upload.entity.DataFile;
import com.eshore.gringotts.web.domain.upload.repository.DataFileRepository;
import com.eshore.gringotts.web.domain.user.entity.User;
@@ -15,17 +17,29 @@ import org.springframework.stereotype.Service;
* @date 2024-11-21
*/
@Service
public class UploadService {
private static final Logger logger = LoggerFactory.getLogger(UploadService.class);
public class DataFileService extends SimpleService<DataFile, Long> {
private static final Logger logger = LoggerFactory.getLogger(DataFileService.class);
private final DataFileRepository dataFileRepository;
private final UserService userService;
public UploadService(DataFileRepository dataFileRepository, UserService userService) {
public DataFileService(DataFileRepository dataFileRepository, UserService userService) {
this.dataFileRepository = dataFileRepository;
this.userService = userService;
}
@Override
protected SimpleRepository<DataFile, Long> repository() {
return dataFileRepository;
}
public DataFile detail(String id) {
if (id == null) {
return null;
}
return detail(Long.valueOf(id));
}
public Long initialDataFile(String filename) {
DataFile dataFile = new DataFile();
dataFile.setFilename(filename);
@@ -45,6 +59,12 @@ public class UploadService {
dataFileRepository.save(dataFile);
}
public static final class DataFileNotFoundException extends RuntimeException {
public DataFileNotFoundException() {
super("文件未找到,请重新上传");
}
}
public static final class UpdateDataFileFailedException extends RuntimeException {
public UpdateDataFileFailedException() {
super("更新文件信息失败,请重新上传");

View File

@@ -1,7 +1,7 @@
package com.eshore.gringotts.web.domain.user.entity;
import com.eshore.gringotts.core.Constants;
import com.eshore.gringotts.web.domain.entity.SimpleEntity;
import com.eshore.gringotts.web.domain.base.entity.SimpleEntity;
import java.time.LocalDateTime;
import javax.persistence.Column;
import javax.persistence.ConstraintMode;
@@ -11,6 +11,8 @@ import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.ForeignKey;
import javax.persistence.JoinColumn;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import lombok.Getter;
@@ -30,6 +32,14 @@ import org.hibernate.annotations.DynamicUpdate;
@Entity
@DynamicUpdate
@Table(name = Constants.TABLE_PREFIX + "user")
@NamedEntityGraph(name = "user.list", attributeNodes = {
@NamedAttributeNode(value = "createdUser"),
})
@NamedEntityGraph(name = "user.detail", attributeNodes = {
@NamedAttributeNode(value = "createdUser"),
@NamedAttributeNode(value = "modifiedUser"),
@NamedAttributeNode(value = "checkedUser"),
})
public class User extends SimpleEntity {
@Column(unique = true, nullable = false)
private String username;

View File

@@ -1,14 +1,11 @@
package com.eshore.gringotts.web.domain.user.repository;
import com.blinkfox.fenix.jpa.FenixJpaRepository;
import com.blinkfox.fenix.specification.FenixJpaSpecificationExecutor;
import com.eshore.gringotts.web.domain.base.repository.SimpleRepository;
import com.eshore.gringotts.web.domain.user.entity.User;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
/**
* User操作
@@ -16,8 +13,14 @@ import org.springframework.transaction.annotation.Transactional;
* @author lanyuanxiaoyao
* @date 2024-11-14
*/
@SuppressWarnings("NullableProblems")
@Repository
public interface UserRepository extends SimpleRepository<User, Long> {
@Override
@EntityGraph(value = "user.list", type = EntityGraph.EntityGraphType.FETCH)
List<User> findAll();
Boolean existsByUsername(String username);
@EntityGraph(value = "user.detail", type = EntityGraph.EntityGraphType.FETCH)
Optional<User> findByUsername(String username);
}