可正常启动
This commit is contained in:
parent
2597946ef8
commit
9089d9bd46
@ -154,6 +154,19 @@
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.retry</groupId>
|
||||
<artifactId>spring-retry</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>32.1.3-jre</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -4,7 +4,9 @@ import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.retry.annotation.EnableRetry;
|
||||
|
||||
@EnableRetry
|
||||
@SpringBootApplication
|
||||
@EnableFeignClients
|
||||
public class BackendApplication {
|
||||
|
||||
@ -7,11 +7,13 @@ import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import com.qqchen.deploy.backend.framework.api.Response;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* 通用REST控制器
|
||||
@ -70,4 +72,17 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
|
||||
List<T> entities = service.findAll(query);
|
||||
return Response.success(converter.toResponseList(entities));
|
||||
}
|
||||
|
||||
@PostMapping("/batch")
|
||||
public CompletableFuture<Response<Void>> batchProcess(@RequestBody List<T> entities) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
service.batchProcess(entities);
|
||||
}).thenApply(v -> Response.success());
|
||||
}
|
||||
|
||||
@GetMapping("/export")
|
||||
public void export(HttpServletResponse response, BaseQuery query) {
|
||||
List<T> data = service.findAll(query);
|
||||
// 导出逻辑
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,8 @@ import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.MappedSuperclass;
|
||||
import jakarta.persistence.OptimisticLockException;
|
||||
import jakarta.persistence.PreUpdate;
|
||||
import jakarta.persistence.Version;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@ -45,9 +47,22 @@ public abstract class Entity<ID extends Serializable> implements Serializable {
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@Version
|
||||
private Integer version;
|
||||
@Column(name = "version", nullable = false)
|
||||
private Integer version = 0;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Boolean deleted = false;
|
||||
|
||||
@PreUpdate
|
||||
protected void onPreUpdate() {
|
||||
if (this.version == null) {
|
||||
this.version = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void checkVersion(Integer expectedVersion) {
|
||||
if (expectedVersion != null && !expectedVersion.equals(this.version)) {
|
||||
throw new OptimisticLockException("数据已被其他用户修改");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,12 @@ public enum ResponseCode {
|
||||
TENANT_NOT_FOUND(1001, "tenant.not.found"),
|
||||
DATA_NOT_FOUND(1002, "data.not.found"),
|
||||
|
||||
// 系统异常 (1开头)
|
||||
OPTIMISTIC_LOCK_ERROR(1003, "system.optimistic.lock.error"), // 乐观锁异常
|
||||
PESSIMISTIC_LOCK_ERROR(1004, "system.pessimistic.lock.error"), // 悲观锁异常
|
||||
CONCURRENT_UPDATE_ERROR(1005, "system.concurrent.update.error"), // 并发更新异常
|
||||
RETRY_EXCEEDED_ERROR(1006, "system.retry.exceeded.error"), // 重试次数超限异常
|
||||
|
||||
// 用户相关错误码(2开头)
|
||||
USER_NOT_FOUND(2001, "user.not.found"),
|
||||
USERNAME_EXISTS(2002, "user.username.exists"),
|
||||
|
||||
@ -1,22 +1,21 @@
|
||||
package com.qqchen.deploy.backend.framework.exception;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.utils.MessageUtils;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
private final ResponseCode errorCode;
|
||||
private final Object[] args;
|
||||
|
||||
public BusinessException(ResponseCode errorCode) {
|
||||
super(MessageUtils.getMessage(errorCode.getMessageKey()));
|
||||
this.errorCode = errorCode;
|
||||
this(errorCode, null);
|
||||
}
|
||||
|
||||
|
||||
public BusinessException(ResponseCode errorCode, Throwable cause) {
|
||||
super(MessageUtils.getMessage(errorCode.getMessageKey()), cause);
|
||||
public BusinessException(ResponseCode errorCode, Object[] args) {
|
||||
super();
|
||||
this.errorCode = errorCode;
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
@ -2,26 +2,59 @@ package com.qqchen.deploy.backend.framework.exception;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.api.Response;
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import jakarta.persistence.OptimisticLockException;
|
||||
import jakarta.persistence.PessimisticLockException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.NoSuchMessageException;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
// @ExceptionHandler(AuthenticationException.class)
|
||||
// public ApiResult<String> handleAuthenticationException(AuthenticationException e) {
|
||||
// log.error("认证异常", e);
|
||||
// if (e instanceof BadCredentialsException) {
|
||||
// return ApiResult.error(401, "用户名或密码错误");
|
||||
// }
|
||||
// return ApiResult.error(401, "认证失败:" + e.getMessage());
|
||||
// }
|
||||
@Autowired
|
||||
private MessageSource messageSource;
|
||||
|
||||
private String getMessage(String key) {
|
||||
try {
|
||||
return messageSource.getMessage(key, null, LocaleContextHolder.getLocale());
|
||||
} catch (NoSuchMessageException e) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
public Response<?> handleApiException(BusinessException e) {
|
||||
return Response.error(e.getErrorCode());
|
||||
String message = messageSource.getMessage(
|
||||
e.getErrorCode().getMessageKey(),
|
||||
e.getArgs(),
|
||||
LocaleContextHolder.getLocale()
|
||||
);
|
||||
return Response.error(e.getErrorCode(), message);
|
||||
}
|
||||
|
||||
@ExceptionHandler(OptimisticLockException.class)
|
||||
public Response<Void> handleOptimisticLockException(OptimisticLockException ex) {
|
||||
log.warn("Optimistic lock exception", ex);
|
||||
return Response.error(ResponseCode.OPTIMISTIC_LOCK_ERROR, getMessage("system.optimistic.lock.error"));
|
||||
}
|
||||
|
||||
@ExceptionHandler(PessimisticLockException.class)
|
||||
public Response<Void> handlePessimisticLockException(PessimisticLockException ex) {
|
||||
log.warn("Pessimistic lock exception", ex);
|
||||
return Response.error(ResponseCode.PESSIMISTIC_LOCK_ERROR, getMessage("system.pessimistic.lock.error"));
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConcurrentModificationException.class)
|
||||
public Response<Void> handleConcurrentModificationException(ConcurrentModificationException ex) {
|
||||
log.warn("Concurrent modification exception", ex);
|
||||
return Response.error(ResponseCode.CONCURRENT_UPDATE_ERROR, getMessage("system.concurrent.update.error"));
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package com.qqchen.deploy.backend.framework.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.LockModeType;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
@ -8,6 +9,8 @@ import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.jpa.repository.Lock;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
@ -121,4 +124,49 @@ public interface IBaseRepository<T extends Entity<ID>, ID extends Serializable>
|
||||
iterable.forEach(result::add);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 批量插入优化
|
||||
@Modifying
|
||||
@Query(value = "INSERT INTO #{#entityName} (id, create_time, create_by) VALUES (:id, :createTime, :createBy)",
|
||||
nativeQuery = true)
|
||||
void batchInsert(
|
||||
@Param("id") ID id,
|
||||
@Param("createTime") LocalDateTime createTime,
|
||||
@Param("createBy") String createBy
|
||||
);
|
||||
|
||||
// 批量更新优化
|
||||
@Modifying
|
||||
@Query("UPDATE #{#entityName} e SET e.updateTime = :updateTime, e.updateBy = :updateBy WHERE e.id IN :ids")
|
||||
void batchUpdate(
|
||||
@Param("ids") Collection<ID> ids,
|
||||
@Param("updateTime") LocalDateTime updateTime,
|
||||
@Param("updateBy") String updateBy
|
||||
);
|
||||
|
||||
// 批量逻辑删除优化
|
||||
@Modifying
|
||||
@Query("UPDATE #{#entityName} e SET e.deleted = true, e.updateTime = :updateTime, e.updateBy = :updateBy WHERE e.id IN :ids")
|
||||
void batchLogicDelete(
|
||||
@Param("ids") Collection<ID> ids,
|
||||
@Param("updateTime") LocalDateTime updateTime,
|
||||
@Param("updateBy") String updateBy
|
||||
);
|
||||
|
||||
// 添加悲观锁查询
|
||||
@Lock(LockModeType.PESSIMISTIC_WRITE)
|
||||
@Query("SELECT e FROM #{#entityName} e WHERE e.id = :id AND e.deleted = false")
|
||||
Optional<T> findByIdWithLock(@Param("id") ID id);
|
||||
|
||||
// 批量更新时添加版本控制
|
||||
@Modifying
|
||||
@Query("UPDATE #{#entityName} e SET e.updateTime = :updateTime, " +
|
||||
"e.updateBy = :updateBy, e.version = e.version + 1 " +
|
||||
"WHERE e.id IN :ids AND e.version = :version")
|
||||
int batchUpdateWithVersion(
|
||||
@Param("ids") Collection<ID> ids,
|
||||
@Param("updateTime") LocalDateTime updateTime,
|
||||
@Param("updateBy") String updateBy,
|
||||
@Param("version") Integer version
|
||||
);
|
||||
}
|
||||
@ -24,4 +24,8 @@ public interface IBaseService<T extends Entity<ID>, ID extends Serializable> {
|
||||
List<T> findAll(BaseQuery query);
|
||||
|
||||
Page<T> page(BaseQuery query);
|
||||
|
||||
void batchProcess(List<T> entities);
|
||||
|
||||
T updateWithRetry(T entity);
|
||||
}
|
||||
@ -5,7 +5,9 @@ import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.enums.QueryType;
|
||||
@ -16,28 +18,41 @@ import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.framework.annotation.QueryField;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import com.qqchen.deploy.backend.framework.utils.EntityPathResolver;
|
||||
import com.qqchen.deploy.backend.framework.security.SecurityUtils;
|
||||
import com.querydsl.core.BooleanBuilder;
|
||||
import com.querydsl.core.types.EntityPath;
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.Predicate;
|
||||
import com.querydsl.core.types.dsl.*;
|
||||
import com.qqchen.deploy.backend.framework.exception.EntityNotFoundException;
|
||||
import jakarta.persistence.OptimisticLockException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.retry.annotation.Backoff;
|
||||
import org.springframework.retry.annotation.Retryable;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@Transactional
|
||||
@Transactional(readOnly = true)
|
||||
@Slf4j
|
||||
public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number & Serializable> implements IBaseService<T, ID> {
|
||||
|
||||
protected final IBaseRepository<T, ID> repository;
|
||||
|
||||
protected final EntityPath<T> entityPath;
|
||||
|
||||
@PersistenceContext
|
||||
protected EntityManager entityManager;
|
||||
|
||||
protected BaseServiceImpl(IBaseRepository<T, ID> repository) {
|
||||
this.repository = repository;
|
||||
this.entityPath = getEntityPath();
|
||||
@ -234,7 +249,7 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
return new BigDecimal(strValue);
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
// 忽略转换错误
|
||||
// 忽略转换误
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -260,8 +275,13 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public T update(T entity) {
|
||||
// 先查询最新版本
|
||||
T currentEntity = findById(entity.getId());
|
||||
// 版本检查
|
||||
currentEntity.checkVersion(entity.getVersion());
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@ -273,7 +293,7 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
@Override
|
||||
public T findById(ID id) {
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new RuntimeException("Entity not found"));
|
||||
.orElseThrow(() -> new EntityNotFoundException(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -312,4 +332,72 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
iterable.forEach(result::add);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
@Override
|
||||
public void batchProcess(List<T> entities) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String operator = SecurityUtils.getCurrentUsername();
|
||||
|
||||
Lists.partition(entities, 500).forEach(batch -> {
|
||||
try {
|
||||
// 加锁查询最新数据
|
||||
List<T> currentEntities = batch.stream()
|
||||
.map(e -> repository.findById(e.getId())
|
||||
.orElseThrow(() -> new EntityNotFoundException(getEntityClass().getSimpleName(), e.getId())))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 版本检查
|
||||
for (int i = 0; i < batch.size(); i++) {
|
||||
currentEntities.get(i).checkVersion(batch.get(i).getVersion());
|
||||
}
|
||||
|
||||
// 批量更新
|
||||
List<ID> ids = currentEntities.stream()
|
||||
.map(Entity::getId)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
repository.batchUpdate(ids, now, operator);
|
||||
repository.flush();
|
||||
entityManager.clear();
|
||||
} catch (OptimisticLockException e) {
|
||||
// 记录失败的批次
|
||||
log.error("Batch update failed for batch size: {}", batch.size(), e);
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Retryable(
|
||||
value = {OptimisticLockException.class},
|
||||
maxAttempts = 3,
|
||||
backoff = @Backoff(delay = 1000, multiplier = 2)
|
||||
)
|
||||
@Override
|
||||
public T updateWithRetry(T entity) {
|
||||
try {
|
||||
return update(entity);
|
||||
} catch (OptimisticLockException e) {
|
||||
// 重试前先刷新实体
|
||||
entityManager.refresh(entity);
|
||||
throw e; // 抛出异常触发重试
|
||||
}
|
||||
}
|
||||
|
||||
// 添加悲观锁查询方法
|
||||
@Transactional
|
||||
public T findByIdWithLock(ID id) {
|
||||
return repository.findByIdWithLock(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(getEntityClass().getSimpleName(), id));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Class<T> getEntityClass() {
|
||||
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class);
|
||||
if (genericTypes != null && genericTypes.length > 0) {
|
||||
return (Class<T>) genericTypes[0];
|
||||
}
|
||||
throw new IllegalStateException("Could not resolve entity class");
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,29 @@
|
||||
# \u4E2D\u6587
|
||||
response.success=\u64CD\u4F5C\u6210\u529F
|
||||
response.error=\u7CFB\u7EDF\u9519\u8BEF
|
||||
response.invalid.param=\u65E0\u6548\u7684\u53C2\u6570
|
||||
response.unauthorized=\u672A\u6388\u6743
|
||||
response.forbidden=\u7981\u6B62\u8BBF\u95EE
|
||||
response.not.found=\u8D44\u6E90\u672A\u627E\u5230
|
||||
response.conflict=\u8D44\u6E90\u51B2\u7A81
|
||||
response.unauthorized.full=\u8BBF\u95EE\u6B64\u8D44\u6E90\u9700\u8981\u5B8C\u5168\u8EAB\u4EFD\u9A8C\u8BC1
|
||||
# 通用响应
|
||||
response.success=操作成功
|
||||
response.error=系统错误
|
||||
response.invalid.param=无效的参数
|
||||
response.unauthorized=未授权
|
||||
response.forbidden=禁止访问
|
||||
response.not.found=资源未找到
|
||||
response.conflict=资源冲突
|
||||
response.unauthorized.full=访问此资源需要完全身份验证
|
||||
|
||||
# 业务错误
|
||||
tenant.not.found=租户不存在
|
||||
data.not.found=找不到ID为{0}的{1}
|
||||
|
||||
tenant.not.found=\u79DF\u6237\u4E0D\u5B58\u5728
|
||||
# 用户相关
|
||||
user.not.found=用户不存在
|
||||
user.username.exists=用户名已存在
|
||||
user.email.exists=邮箱已存在
|
||||
|
||||
user.not.found=\u7528\u6237\u4E0D\u5B58\u5728
|
||||
user.username.exists=\u7528\u6237\u540D\u5DF2\u5B58\u5728
|
||||
user.email.exists=\u90AE\u7BB1\u5DF2\u5B58\u5728
|
||||
# 系统异常消息
|
||||
system.optimistic.lock.error=数据已被其他用户修改,请刷新后重试
|
||||
system.pessimistic.lock.error=数据正被其他用户操作,请稍后重试
|
||||
system.concurrent.update.error=并发更新冲突,请重试
|
||||
system.retry.exceeded.error=操作重试次数超限,请稍后再试
|
||||
|
||||
data.not.found=数据不存在
|
||||
# Entity Not Found Messages
|
||||
entity.not.found.id=找不到ID为{0}的实体
|
||||
entity.not.found.message={0}
|
||||
entity.not.found.name.id=找不到ID为{1}的{0}
|
||||
@ -1,4 +1,4 @@
|
||||
# \u9ED8\u8BA4\u8BED\u8A00\uFF08\u82F1\u6587\uFF09
|
||||
# Common Response
|
||||
response.success=Success
|
||||
response.error=System Error
|
||||
response.invalid.param=Invalid Parameter
|
||||
@ -8,11 +8,22 @@ response.not.found=Resource Not Found
|
||||
response.conflict=Resource Conflict
|
||||
response.unauthorized.full=Full authentication is required to access this resource
|
||||
|
||||
|
||||
# Business Error
|
||||
tenant.not.found=Tenant not found
|
||||
data.not.found={0} with id {1} not found
|
||||
|
||||
# User Related
|
||||
user.not.found=User not found
|
||||
user.username.exists=Username already exists
|
||||
user.email.exists=Email already exists
|
||||
|
||||
data.not.found=Data not found
|
||||
# System Exception Messages
|
||||
system.optimistic.lock.error=Data has been modified by another user, please refresh and try again
|
||||
system.pessimistic.lock.error=Data is being operated by another user, please try again later
|
||||
system.concurrent.update.error=Concurrent update conflict, please try again
|
||||
system.retry.exceeded.error=Operation retry limit exceeded, please try again later
|
||||
|
||||
# Entity Not Found Messages
|
||||
entity.not.found.id=Entity with id {0} not found
|
||||
entity.not.found.message={0}
|
||||
entity.not.found.name.id={0} with id {1} not found
|
||||
@ -1,16 +1,29 @@
|
||||
# \u4E2D\u6587
|
||||
response.success=\u64CD\u4F5C\u6210\u529F
|
||||
response.error=\u7CFB\u7EDF\u9519\u8BEF
|
||||
response.invalid.param=\u65E0\u6548\u7684\u53C2\u6570
|
||||
response.unauthorized=\u672A\u6388\u6743
|
||||
response.forbidden=\u7981\u6B62\u8BBF\u95EE
|
||||
response.not.found=\u8D44\u6E90\u672A\u627E\u5230
|
||||
response.conflict=\u8D44\u6E90\u51B2\u7A81
|
||||
response.unauthorized.full=\u8BBF\u95EE\u6B64\u8D44\u6E90\u9700\u8981\u5B8C\u5168\u8EAB\u4EFD\u9A8C\u8BC1
|
||||
# 通用响应
|
||||
response.success=操作成功
|
||||
response.error=系统错误
|
||||
response.invalid.param=无效的参数
|
||||
response.unauthorized=未授权
|
||||
response.forbidden=禁止访问
|
||||
response.not.found=资源未找到
|
||||
response.conflict=资源冲突
|
||||
response.unauthorized.full=访问此资源需要完全身份验证
|
||||
|
||||
tenant.not.found=\u79DF\u6237\u4E0D\u5B58\u5728
|
||||
# 业务错误
|
||||
tenant.not.found=租户不存在
|
||||
data.not.found=数据不存在
|
||||
|
||||
user.not.found=\u7528\u6237\u4E0D\u5B58\u5728
|
||||
user.username.exists=\u7528\u6237\u540D\u5DF2\u5B58\u5728
|
||||
user.email.exists=\u90AE\u7BB1\u5DF2\u5B58\u5728
|
||||
data.not.found=数据不存在
|
||||
# 用户相关
|
||||
user.not.found=用户不存在
|
||||
user.username.exists=用户名已存在
|
||||
user.email.exists=邮箱已存在
|
||||
|
||||
# 系统异常消息
|
||||
system.optimistic.lock.error=数据已被其他用户修改,请刷新后重试
|
||||
system.pessimistic.lock.error=数据正被其他用户操作,请稍后重试
|
||||
system.concurrent.update.error=并发更新冲突,请重试
|
||||
system.retry.exceeded.error=操作重试次数超限,请稍后再试
|
||||
|
||||
# Entity Not Found Messages
|
||||
entity.not.found.id=找不到ID为{0}的实体
|
||||
entity.not.found.message={0}
|
||||
entity.not.found.name.id=找不到ID为{1}的{0}
|
||||
Loading…
Reference in New Issue
Block a user