可正常启动
This commit is contained in:
parent
bd8340355b
commit
7e40c620e7
@ -1,11 +1,12 @@
|
||||
package com.qqchen.deploy.backend.api;
|
||||
|
||||
import com.qqchen.deploy.backend.dto.RoleDTO;
|
||||
import com.qqchen.deploy.backend.dto.query.UserQuery;
|
||||
import com.qqchen.deploy.backend.dto.request.UserRequest;
|
||||
import com.qqchen.deploy.backend.framework.controller.BaseController;
|
||||
import com.qqchen.deploy.backend.framework.api.Response;
|
||||
import com.qqchen.deploy.backend.entity.User;
|
||||
import com.qqchen.deploy.backend.dto.query.UserQuery;
|
||||
import com.qqchen.deploy.backend.dto.request.UserRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.UserResponse;
|
||||
import com.qqchen.deploy.backend.dto.UserDTO;
|
||||
import com.qqchen.deploy.backend.dto.request.LoginRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.LoginResponse;
|
||||
import com.qqchen.deploy.backend.service.IUserService;
|
||||
@ -20,7 +21,7 @@ import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/users")
|
||||
public class UserApiController extends BaseController<User, Long, UserQuery, UserRequest, UserResponse> {
|
||||
public class UserApiController extends BaseController<User, UserDTO, Long, UserQuery> {
|
||||
|
||||
private final IUserService userService;
|
||||
|
||||
@ -37,12 +38,12 @@ public class UserApiController extends BaseController<User, Long, UserQuery, Use
|
||||
|
||||
@Operation(summary = "用户注册")
|
||||
@PostMapping("/register")
|
||||
public Response<UserResponse> register(@Validated @RequestBody UserRequest request) {
|
||||
public Response<UserDTO> register(@Validated @RequestBody UserRequest request) {
|
||||
return Response.success(userService.register(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exportData(HttpServletResponse response, List<UserResponse> data) {
|
||||
protected void exportData(HttpServletResponse response, List<UserDTO> data) {
|
||||
response.setContentType("application/vnd.ms-excel");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=users.xlsx");
|
||||
|
||||
@ -52,4 +53,16 @@ public class UserApiController extends BaseController<User, Long, UserQuery, Use
|
||||
throw new RuntimeException("Export failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/roles")
|
||||
@Operation(summary = "获取当前用户的角色")
|
||||
public Response<List<RoleDTO>> getCurrentUserRoles() {
|
||||
return Response.success(userService.getCurrentUserRoles());
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/roles")
|
||||
@Operation(summary = "获取指定用户的角色")
|
||||
public Response<List<RoleDTO>> getUserRoles(@PathVariable Long id) {
|
||||
return Response.success(userService.getUserRoles(id));
|
||||
}
|
||||
}
|
||||
@ -1,19 +1,35 @@
|
||||
//package com.qqchen.deploy.backend.controller;
|
||||
//
|
||||
//import com.qqchen.deploy.backend.entity.Tenant;
|
||||
//import com.qqchen.deploy.backend.framework.controller.BaseController;
|
||||
//import com.qqchen.deploy.backend.service.ITenantService;
|
||||
//import com.qqchen.deploy.backend.dto.request.TenantRequest;
|
||||
//import com.qqchen.deploy.backend.dto.response.TenantResponse;
|
||||
//import com.qqchen.deploy.backend.query.TenantQuery;
|
||||
//import org.springframework.web.bind.annotation.RequestMapping;
|
||||
//import org.springframework.web.bind.annotation.RestController;
|
||||
//
|
||||
//@RestController
|
||||
//@RequestMapping("/tenants")
|
||||
//public class TenantController extends BaseController<Tenant, Long, TenantQuery, TenantRequest, TenantResponse> {
|
||||
//
|
||||
// public TenantController(ITenantService service) {
|
||||
// super(service);
|
||||
// }
|
||||
//}
|
||||
package com.qqchen.deploy.backend.controller;
|
||||
|
||||
import com.qqchen.deploy.backend.dto.query.TenantQuery;
|
||||
import com.qqchen.deploy.backend.entity.Tenant;
|
||||
import com.qqchen.deploy.backend.framework.controller.BaseController;
|
||||
import com.qqchen.deploy.backend.service.ITenantService;
|
||||
import com.qqchen.deploy.backend.dto.TenantDTO;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/tenants")
|
||||
public class TenantController extends BaseController<Tenant, TenantDTO, Long, TenantQuery> {
|
||||
|
||||
public TenantController(ITenantService service) {
|
||||
super(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exportData(HttpServletResponse response, List<TenantDTO> data) {
|
||||
response.setContentType("application/vnd.ms-excel");
|
||||
response.setHeader("Content-Disposition", "attachment;filename=tenants.xlsx");
|
||||
|
||||
try (OutputStream out = response.getOutputStream()) {
|
||||
// ExcelUtils.export(data, out);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Export failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
package com.qqchen.deploy.backend.converter;
|
||||
|
||||
import com.qqchen.deploy.backend.dto.RoleDTO;
|
||||
import com.qqchen.deploy.backend.entity.Role;
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface RoleConverter extends BaseConverter<Role, RoleDTO> {
|
||||
// MapStruct 会自动实现必要的方法
|
||||
}
|
||||
@ -1,13 +1,11 @@
|
||||
package com.qqchen.deploy.backend.converter;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import com.qqchen.deploy.backend.dto.request.TenantRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.TenantResponse;
|
||||
import com.qqchen.deploy.backend.dto.TenantDTO;
|
||||
import com.qqchen.deploy.backend.entity.Tenant;
|
||||
import com.qqchen.deploy.backend.framework.converter.AbstractConverter;
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface TenantConverter extends BaseConverter<Tenant, TenantRequest, TenantResponse> {
|
||||
// MapStruct 会自动实现转换方法
|
||||
@Mapper(config = BaseConverter.class)
|
||||
public abstract class TenantConverter extends AbstractConverter<Tenant, TenantDTO> implements BaseConverter<Tenant, TenantDTO> {
|
||||
}
|
||||
@ -1,28 +1,11 @@
|
||||
package com.qqchen.deploy.backend.converter;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.converter.AbstractConverter;
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import com.qqchen.deploy.backend.entity.User;
|
||||
import com.qqchen.deploy.backend.dto.request.UserRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.UserResponse;
|
||||
import com.qqchen.deploy.backend.dto.UserDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.mapstruct.ReportingPolicy;
|
||||
|
||||
@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE)
|
||||
public interface UserConverter extends BaseConverter<User, UserRequest, UserResponse> {
|
||||
|
||||
@Override
|
||||
@Mapping(target = "id", ignore = true)
|
||||
@Mapping(target = "enabled", constant = "true")
|
||||
User toEntity(UserRequest request);
|
||||
|
||||
@Override
|
||||
@Mapping(target = "password", ignore = true)
|
||||
UserResponse toResponse(User user);
|
||||
|
||||
@Override
|
||||
@Mapping(target = "id", ignore = true)
|
||||
@Mapping(target = "enabled", ignore = true)
|
||||
void updateEntity(@MappingTarget User user, UserRequest request);
|
||||
@Mapper(config = BaseConverter.class)
|
||||
public abstract class UserConverter extends AbstractConverter<User, UserDTO> implements BaseConverter<User, UserDTO> {
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
package com.qqchen.deploy.backend.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class RoleDTO extends BaseDTO {
|
||||
private String name;
|
||||
private String code;
|
||||
private String description;
|
||||
private Integer sort;
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
package com.qqchen.deploy.backend.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TenantDTO extends BaseDTO {
|
||||
private String name;
|
||||
private String code;
|
||||
private String description;
|
||||
private Boolean enabled;
|
||||
private String contactName;
|
||||
private String contactPhone;
|
||||
private String contactEmail;
|
||||
private String address;
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.qqchen.deploy.backend.dto;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserDTO extends BaseDTO {
|
||||
private String username;
|
||||
private String nickname;
|
||||
private String email;
|
||||
private String phone;
|
||||
private Boolean enabled;
|
||||
private Set<RoleDTO> roles;
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
package com.qqchen.deploy.backend.dto.request;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TenantRequest extends BaseRequest {
|
||||
|
||||
@NotBlank(message = "租户名称不能为空")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "租户编码不能为空")
|
||||
private String code;
|
||||
|
||||
@NotBlank(message = "租户维护人")
|
||||
private String contactName;
|
||||
|
||||
@NotBlank(message = "租户维护人电话")
|
||||
private String contactPhone;
|
||||
|
||||
}
|
||||
@ -1,6 +1,5 @@
|
||||
package com.qqchen.deploy.backend.dto.request;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
@ -8,8 +7,7 @@ import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class UserRequest extends BaseRequest {
|
||||
public class UserRequest {
|
||||
|
||||
|
||||
@NotBlank(message = "用户名不能为空")
|
||||
@ -24,6 +22,9 @@ public class UserRequest extends BaseRequest {
|
||||
@Size(min = 6, max = 20, message = "密码长度必须在6-20之间")
|
||||
private String password;
|
||||
|
||||
@NotBlank(message = "确认密码不能为空")
|
||||
private String confirmPassword;
|
||||
|
||||
private String nickname;
|
||||
|
||||
private String phone;
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
package com.qqchen.deploy.backend.dto.response;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class TenantResponse extends BaseResponse {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String code;
|
||||
|
||||
private String contactName;
|
||||
|
||||
private String contactPhone;
|
||||
|
||||
private String email;
|
||||
|
||||
private String address;
|
||||
|
||||
private Boolean enabled = true;
|
||||
}
|
||||
@ -3,10 +3,13 @@ package com.qqchen.deploy.backend.entity;
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@Data
|
||||
@ -29,4 +32,7 @@ public class Role extends Entity<Long> {
|
||||
@Column(nullable = false)
|
||||
private Integer sort = 0;
|
||||
|
||||
@ManyToMany(mappedBy = "roles")
|
||||
private Set<User> users = new HashSet<>();
|
||||
|
||||
}
|
||||
@ -3,9 +3,15 @@ package com.qqchen.deploy.backend.entity;
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ -30,4 +36,18 @@ public class User extends Entity<Long> {
|
||||
@Column(nullable = false)
|
||||
private Boolean enabled = true;
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(
|
||||
name = "sys_user_role", // 中间表名称
|
||||
joinColumns = @JoinColumn(
|
||||
name = "user_id", // 中间表中关联当前实体的外键名
|
||||
referencedColumnName = "id" // 当前实体的主键
|
||||
),
|
||||
inverseJoinColumns = @JoinColumn(
|
||||
name = "role_id", // 中间表中关联目标实体的外键名
|
||||
referencedColumnName = "id" // 目标实体的主键
|
||||
)
|
||||
)
|
||||
private Set<Role> roles = new HashSet<>();
|
||||
|
||||
}
|
||||
@ -1,32 +1,32 @@
|
||||
package com.qqchen.deploy.backend.entity;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@jakarta.persistence.Entity
|
||||
@Table(name = "sys_user_role")
|
||||
@LogicDelete
|
||||
public class UserRole extends Entity<Long> {
|
||||
|
||||
@Column(name = "user_id")
|
||||
private Long userId;
|
||||
|
||||
@Column(name = "role_id")
|
||||
private Long roleId;
|
||||
|
||||
// 添加构造方法
|
||||
protected UserRole() {
|
||||
// JPA需要无参构造方法
|
||||
}
|
||||
|
||||
public UserRole(Long userId, Long roleId) {
|
||||
this.userId = userId;
|
||||
this.roleId = roleId;
|
||||
}
|
||||
}
|
||||
//package com.qqchen.deploy.backend.entity;
|
||||
//
|
||||
//import com.qqchen.deploy.backend.framework.annotation.LogicDelete;
|
||||
//import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
//import jakarta.persistence.Column;
|
||||
//import jakarta.persistence.Table;
|
||||
//import lombok.Data;
|
||||
//import lombok.EqualsAndHashCode;
|
||||
//
|
||||
//@Data
|
||||
//@EqualsAndHashCode(callSuper = true)
|
||||
//@jakarta.persistence.Entity
|
||||
//@Table(name = "sys_user_role")
|
||||
//@LogicDelete
|
||||
//public class UserRole extends Entity<Long> {
|
||||
//
|
||||
// @Column(name = "user_id")
|
||||
// private Long userId;
|
||||
//
|
||||
// @Column(name = "role_id")
|
||||
// private Long roleId;
|
||||
//
|
||||
// // 添加构造方法
|
||||
// protected UserRole() {
|
||||
// // JPA需要无参构造方法
|
||||
// }
|
||||
//
|
||||
// public UserRole(Long userId, Long roleId) {
|
||||
// this.userId = userId;
|
||||
// this.roleId = roleId;
|
||||
// }
|
||||
//}
|
||||
@ -1,9 +1,8 @@
|
||||
package com.qqchen.deploy.backend.framework.controller;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
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;
|
||||
@ -19,23 +18,22 @@ import java.util.concurrent.CompletableFuture;
|
||||
* 通用REST控制器
|
||||
*/
|
||||
@Validated
|
||||
public abstract class BaseController<T extends Entity<ID>, ID extends Serializable,
|
||||
Q extends BaseQuery, REQ extends BaseRequest, RESP extends BaseResponse> {
|
||||
public abstract class BaseController<T extends Entity<ID>, D extends BaseDTO, ID extends Serializable, Q extends BaseQuery> {
|
||||
|
||||
protected final IBaseService<T, ID, REQ, RESP> service;
|
||||
protected final IBaseService<T, D, ID> service;
|
||||
|
||||
protected BaseController(IBaseService<T, ID, REQ, RESP> service) {
|
||||
protected BaseController(IBaseService<T, D, ID> service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
public Response<RESP> create(@Validated @RequestBody REQ request) {
|
||||
return Response.success(service.create(request));
|
||||
public Response<D> create(@Validated @RequestBody D dto) {
|
||||
return Response.success(service.create(dto));
|
||||
}
|
||||
|
||||
@PutMapping("/{id}")
|
||||
public Response<RESP> update(@PathVariable ID id, @Validated @RequestBody REQ request) {
|
||||
return Response.success(service.update(id, request));
|
||||
public Response<D> update(@PathVariable ID id, @Validated @RequestBody D dto) {
|
||||
return Response.success(service.update(id, dto));
|
||||
}
|
||||
|
||||
@DeleteMapping("/{id}")
|
||||
@ -45,35 +43,35 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
|
||||
}
|
||||
|
||||
@GetMapping("/{id}")
|
||||
public Response<RESP> findById(@PathVariable ID id) {
|
||||
public Response<D> findById(@PathVariable ID id) {
|
||||
return Response.success(service.findById(id));
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public Response<List<RESP>> findAll() {
|
||||
public Response<List<D>> findAll() {
|
||||
return Response.success(service.findAll());
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
public Response<Page<RESP>> page(Q query) {
|
||||
public Response<Page<D>> page(Q query) {
|
||||
return Response.success(service.page(query));
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public Response<List<RESP>> findAll(Q query) {
|
||||
public Response<List<D>> findAll(Q query) {
|
||||
return Response.success(service.findAll(query));
|
||||
}
|
||||
|
||||
@PostMapping("/batch")
|
||||
public CompletableFuture<Response<Void>> batchProcess(@RequestBody List<T> entities) {
|
||||
public CompletableFuture<Response<Void>> batchProcess(@RequestBody List<D> dtos) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
service.batchProcess(entities);
|
||||
service.batchProcess(dtos);
|
||||
}).thenApply(v -> Response.success());
|
||||
}
|
||||
|
||||
@GetMapping("/export")
|
||||
public void export(HttpServletResponse response, Q query) {
|
||||
List<RESP> data = service.findAll(query);
|
||||
List<D> data = service.findAll(query);
|
||||
exportData(response, data);
|
||||
}
|
||||
|
||||
@ -82,5 +80,5 @@ public abstract class BaseController<T extends Entity<ID>, ID extends Serializab
|
||||
* @param response HTTP响应
|
||||
* @param data 要导出的数据
|
||||
*/
|
||||
protected abstract void exportData(HttpServletResponse response, List<RESP> data);
|
||||
protected abstract void exportData(HttpServletResponse response, List<D> data);
|
||||
}
|
||||
@ -1,26 +1,29 @@
|
||||
package com.qqchen.deploy.backend.framework.converter;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
|
||||
public abstract class AbstractConverter<T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
|
||||
implements BaseConverter<T, REQ, RESP> {
|
||||
public abstract class AbstractConverter<T extends Entity<?>, D extends BaseDTO> {
|
||||
|
||||
private final Class<T> entityClass;
|
||||
private final Class<D> dtoClass;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected AbstractConverter() {
|
||||
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), AbstractConverter.class);
|
||||
if (genericTypes == null || genericTypes.length < 3) {
|
||||
throw new IllegalStateException("Could not resolve entity class");
|
||||
if (genericTypes == null || genericTypes.length < 2) {
|
||||
throw new IllegalStateException("Could not resolve generic types");
|
||||
}
|
||||
this.entityClass = (Class<T>) genericTypes[0];
|
||||
this.dtoClass = (Class<D>) genericTypes[1];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getEntityClass() {
|
||||
return entityClass;
|
||||
}
|
||||
|
||||
public Class<D> getDtoClass() {
|
||||
return dtoClass;
|
||||
}
|
||||
}
|
||||
@ -1,40 +1,63 @@
|
||||
package com.qqchen.deploy.backend.framework.converter;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.mapstruct.Mappings;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public interface BaseConverter<T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse> {
|
||||
@org.mapstruct.MapperConfig(
|
||||
componentModel = "spring",
|
||||
unmappedTargetPolicy = org.mapstruct.ReportingPolicy.IGNORE
|
||||
)
|
||||
public interface BaseConverter<T extends Entity<?>, D extends BaseDTO> {
|
||||
|
||||
// Request -> Domain
|
||||
T toEntity(REQ request);
|
||||
@Mappings({
|
||||
@Mapping(target = "id", source = "id"),
|
||||
@Mapping(target = "createTime", source = "createTime"),
|
||||
@Mapping(target = "createBy", source = "createBy"),
|
||||
@Mapping(target = "updateTime", source = "updateTime"),
|
||||
@Mapping(target = "updateBy", source = "updateBy"),
|
||||
@Mapping(target = "version", source = "version"),
|
||||
@Mapping(target = "deleted", source = "deleted")
|
||||
})
|
||||
D toDto(T entity);
|
||||
|
||||
// Domain -> Response
|
||||
RESP toResponse(T entity);
|
||||
@Mappings({
|
||||
@Mapping(target = "id", source = "id"),
|
||||
@Mapping(target = "createTime", source = "createTime"),
|
||||
@Mapping(target = "createBy", source = "createBy"),
|
||||
@Mapping(target = "updateTime", source = "updateTime"),
|
||||
@Mapping(target = "updateBy", source = "updateBy"),
|
||||
@Mapping(target = "version", source = "version"),
|
||||
@Mapping(target = "deleted", source = "deleted")
|
||||
})
|
||||
T toEntity(D dto);
|
||||
|
||||
// Domain List -> Response List
|
||||
List<RESP> toResponseList(List<T> entityList);
|
||||
@Mappings({
|
||||
@Mapping(target = "id", ignore = true),
|
||||
@Mapping(target = "createTime", ignore = true),
|
||||
@Mapping(target = "createBy", ignore = true),
|
||||
@Mapping(target = "version", ignore = true),
|
||||
@Mapping(target = "deleted", ignore = true)
|
||||
})
|
||||
void updateEntity(@MappingTarget T entity, D dto);
|
||||
|
||||
// 更新实体
|
||||
void updateEntity(@MappingTarget T entity, REQ request);
|
||||
List<D> toDtoList(List<T> entityList);
|
||||
|
||||
// 转换分页结果
|
||||
default Page<RESP> toResponsePage(Page<T> page) {
|
||||
return page.map(this::toResponse);
|
||||
default Page<D> toDtoPage(Page<T> page) {
|
||||
return page.map(this::toDto);
|
||||
}
|
||||
|
||||
// 获取实体类类型
|
||||
@SuppressWarnings("unchecked")
|
||||
default Class<T> getEntityClass() {
|
||||
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseConverter.class);
|
||||
if (genericTypes == null || genericTypes.length < 3) {
|
||||
throw new IllegalStateException("Could not resolve entity class");
|
||||
}
|
||||
return (Class<T>) genericTypes[0];
|
||||
default List<T> toEntityList(List<D> dtos) {
|
||||
if (dtos == null) return null;
|
||||
return dtos.stream()
|
||||
.map(this::toEntity)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package com.qqchen.deploy.backend.framework.converter;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@Service
|
||||
public class ConversionService {
|
||||
|
||||
private final Map<Class<?>, BaseConverter<?, ?, ?>> converterMap = new ConcurrentHashMap<>();
|
||||
|
||||
@Autowired
|
||||
public void setConverters(List<BaseConverter<?, ?, ?>> converters) {
|
||||
converters.forEach(converter -> {
|
||||
Class<?> entityClass = converter.getEntityClass();
|
||||
converterMap.put(entityClass, converter);
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
|
||||
BaseConverter<T, REQ, RESP> getConverter(Class<T> entityClass) {
|
||||
BaseConverter<?, ?, ?> converter = converterMap.get(entityClass);
|
||||
if (converter == null) {
|
||||
throw new IllegalArgumentException("No converter found for entity class: " + entityClass.getName());
|
||||
}
|
||||
return (BaseConverter<T, REQ, RESP>) converter;
|
||||
}
|
||||
|
||||
@Cacheable(value = "conversion", key = "#request.class.name + '_' + #entityClass.name")
|
||||
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
|
||||
T toEntity(REQ request, Class<T> entityClass) {
|
||||
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
|
||||
return converter.toEntity(request);
|
||||
}
|
||||
|
||||
@Cacheable(value = "conversion", key = "#entity.class.name + '_response'")
|
||||
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
|
||||
RESP toResponse(T entity) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> entityClass = (Class<T>) entity.getClass();
|
||||
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
|
||||
return converter.toResponse(entity);
|
||||
}
|
||||
|
||||
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
|
||||
List<RESP> toResponseList(List<T> entities) {
|
||||
if (entities.isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> entityClass = (Class<T>) entities.get(0).getClass();
|
||||
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
|
||||
return converter.toResponseList(entities);
|
||||
}
|
||||
|
||||
public <T extends Entity<?>, REQ extends BaseRequest, RESP extends BaseResponse>
|
||||
void updateEntity(T entity, REQ request) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> entityClass = (Class<T>) entity.getClass();
|
||||
BaseConverter<T, REQ, RESP> converter = getConverter(entityClass);
|
||||
converter.updateEntity(entity, request);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package com.qqchen.deploy.backend.framework.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class BaseDTO implements Serializable {
|
||||
private Long id;
|
||||
private LocalDateTime createTime;
|
||||
private String createBy;
|
||||
private LocalDateTime updateTime;
|
||||
private String updateBy;
|
||||
private Integer version;
|
||||
private Boolean deleted;
|
||||
|
||||
// 扩展字段,用于存储额外的属性
|
||||
private Map<String, Object> extraData;
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
package com.qqchen.deploy.backend.framework.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public abstract class BaseRequest implements Serializable {
|
||||
|
||||
private String operator; // 操作人
|
||||
|
||||
private Long timestamp; // 操作时间戳
|
||||
|
||||
private String traceId; // 请求追踪ID
|
||||
|
||||
private String clientIp; // 客户端IP
|
||||
|
||||
private String clientType; // 客户端类型
|
||||
|
||||
private String appVersion; // 应用版本
|
||||
}
|
||||
@ -1,8 +1,7 @@
|
||||
package com.qqchen.deploy.backend.framework.service;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
@ -12,28 +11,28 @@ import java.util.List;
|
||||
/**
|
||||
* 通用服务接口
|
||||
*/
|
||||
public interface IBaseService<T extends Entity<ID>, ID extends Serializable, REQ extends BaseRequest, RESP extends BaseResponse> {
|
||||
RESP create(REQ request);
|
||||
public interface IBaseService<T extends Entity<ID>, D extends BaseDTO, ID extends Serializable> {
|
||||
D create(D dto);
|
||||
|
||||
RESP update(ID id, REQ request);
|
||||
D update(ID id, D dto);
|
||||
|
||||
void delete(ID id);
|
||||
|
||||
RESP findById(ID id);
|
||||
D findById(ID id);
|
||||
|
||||
List<RESP> findAll();
|
||||
List<D> findAll();
|
||||
|
||||
List<RESP> findAll(BaseQuery query);
|
||||
Page<D> page(BaseQuery query);
|
||||
|
||||
Page<RESP> page(BaseQuery query);
|
||||
List<D> findAll(BaseQuery query);
|
||||
|
||||
void batchProcess(List<T> entities);
|
||||
|
||||
RESP updateWithRetry(ID id, REQ request);
|
||||
void batchProcess(List<D> dtos);
|
||||
|
||||
T findEntityById(ID id);
|
||||
|
||||
T createEntity(T entity);
|
||||
Class<T> getEntityClass();
|
||||
|
||||
T updateEntity(T entity);
|
||||
T findByIdWithLock(ID id);
|
||||
|
||||
D updateWithRetry(ID id, D dto);
|
||||
}
|
||||
@ -2,17 +2,15 @@ package com.qqchen.deploy.backend.framework.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
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.converter.ConversionService;
|
||||
import com.qqchen.deploy.backend.framework.converter.BaseConverter;
|
||||
import com.qqchen.deploy.backend.framework.domain.Entity;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseRequest;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseResponse;
|
||||
import com.qqchen.deploy.backend.framework.dto.BaseDTO;
|
||||
import com.qqchen.deploy.backend.framework.enums.QueryType;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import com.qqchen.deploy.backend.framework.query.DateRange;
|
||||
@ -47,19 +45,19 @@ import java.lang.reflect.Field;
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
@Slf4j
|
||||
public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number & Serializable,
|
||||
REQ extends BaseRequest, RESP extends BaseResponse> implements IBaseService<T, ID, REQ, RESP> {
|
||||
public abstract class BaseServiceImpl<T extends Entity<ID>, D extends BaseDTO, ID extends Serializable>
|
||||
implements IBaseService<T, D, ID> {
|
||||
|
||||
protected final IBaseRepository<T, ID> repository;
|
||||
protected final ConversionService conversionService;
|
||||
protected final BaseConverter<T, D> converter;
|
||||
protected final EntityPath<T> entityPath;
|
||||
|
||||
@PersistenceContext
|
||||
protected EntityManager entityManager;
|
||||
|
||||
protected BaseServiceImpl(IBaseRepository<T, ID> repository, ConversionService conversionService) {
|
||||
protected BaseServiceImpl(IBaseRepository<T, ID> repository, BaseConverter<T, D> converter) {
|
||||
this.repository = repository;
|
||||
this.conversionService = conversionService;
|
||||
this.converter = converter;
|
||||
this.entityPath = getEntityPath();
|
||||
}
|
||||
|
||||
@ -82,18 +80,52 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<RESP> page(BaseQuery query) {
|
||||
BooleanBuilder builder = createQueryPredicate(query);
|
||||
Page<T> page = repository.findAll(builder, createPageRequest(query));
|
||||
return page.map(entity -> conversionService.toResponse(entity));
|
||||
@Transactional
|
||||
public D create(D dto) {
|
||||
T entity = converter.toEntity(dto);
|
||||
T savedEntity = repository.save(entity);
|
||||
return converter.toDto(savedEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RESP> findAll(BaseQuery query) {
|
||||
@Transactional
|
||||
public D update(ID id, D dto) {
|
||||
T entity = findEntityById(id);
|
||||
converter.updateEntity(entity, dto);
|
||||
T updatedEntity = repository.save(entity);
|
||||
return converter.toDto(updatedEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void delete(ID id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public D findById(ID id) {
|
||||
T entity = findEntityById(id);
|
||||
return converter.toDto(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<D> findAll() {
|
||||
List<T> entities = repository.findAll();
|
||||
return converter.toDtoList(entities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<D> findAll(BaseQuery query) {
|
||||
BooleanBuilder builder = createQueryPredicate(query);
|
||||
Sort sort = createSort(query);
|
||||
List<T> entities = repository.findAllByCondition(builder, sort);
|
||||
return conversionService.toResponseList(entities);
|
||||
return converter.toDtoList(entities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<D> page(BaseQuery query) {
|
||||
Page<T> page = repository.findAll(createQueryPredicate(query), createPageRequest(query));
|
||||
return converter.toDtoPage(page);
|
||||
}
|
||||
|
||||
protected BooleanBuilder createQueryPredicate(BaseQuery query) {
|
||||
@ -101,11 +133,12 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
if (query != null) {
|
||||
buildQueryPredicate(query, builder);
|
||||
}
|
||||
handleSoftDelete(builder);
|
||||
handleSoftDelete(builder, query);
|
||||
return builder;
|
||||
}
|
||||
|
||||
protected void handleSoftDelete(BooleanBuilder builder) {
|
||||
protected void handleSoftDelete(BooleanBuilder builder, BaseQuery query) {
|
||||
if (query == null || query.getDeleted() == null) {
|
||||
Class<T> entityClass = getEntityClass();
|
||||
LogicDelete softDelete = entityClass.getAnnotation(LogicDelete.class);
|
||||
if (softDelete != null && softDelete.value()) {
|
||||
@ -114,6 +147,12 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
builder.and(((BooleanPath) deletedPath).eq(false));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Path<?> deletedPath = EntityPathResolver.getPath(entityPath, "deleted");
|
||||
if (deletedPath instanceof BooleanPath) {
|
||||
builder.and(((BooleanPath) deletedPath).eq(query.getDeleted()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Sort createSort(BaseQuery query) {
|
||||
@ -294,50 +333,16 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = false)
|
||||
public RESP create(REQ request) {
|
||||
T entity = conversionService.toEntity(request, getEntityClass());
|
||||
T savedEntity = createEntity(entity);
|
||||
return conversionService.toResponse(savedEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = false)
|
||||
public RESP update(ID id, REQ request) {
|
||||
T entity = findEntityById(id);
|
||||
conversionService.updateEntity(entity, request);
|
||||
T updatedEntity = updateEntity(entity);
|
||||
return conversionService.toResponse(updatedEntity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = false)
|
||||
public void delete(ID id) {
|
||||
repository.deleteById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RESP findById(ID id) {
|
||||
T entity = findEntityById(id);
|
||||
return conversionService.toResponse(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RESP> findAll() {
|
||||
List<T> entities = repository.findAll();
|
||||
return conversionService.toResponseList(entities);
|
||||
}
|
||||
|
||||
@Transactional(
|
||||
readOnly = false,
|
||||
propagation = Propagation.REQUIRES_NEW
|
||||
)
|
||||
@Override
|
||||
public void batchProcess(List<T> entities) {
|
||||
public void batchProcess(List<D> dtos) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
String operator = SecurityUtils.getCurrentUsername();
|
||||
|
||||
List<T> entities = converter.toEntityList(dtos);
|
||||
Lists.partition(entities, 500).forEach(batch -> {
|
||||
try {
|
||||
// 加锁查询最新数据
|
||||
@ -360,7 +365,6 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
repository.flush();
|
||||
entityManager.clear();
|
||||
} catch (OptimisticLockException e) {
|
||||
// 记录失败的批次
|
||||
log.error("Batch update failed for batch size: {}", batch.size(), e);
|
||||
throw e;
|
||||
}
|
||||
@ -373,10 +377,9 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
maxAttempts = 3,
|
||||
backoff = @Backoff(delay = 1000, multiplier = 2)
|
||||
)
|
||||
@Override
|
||||
public RESP updateWithRetry(ID id, REQ request) {
|
||||
public D updateWithRetry(ID id, D dto) {
|
||||
try {
|
||||
return update(id, request);
|
||||
return update(id, dto);
|
||||
} catch (OptimisticLockException e) {
|
||||
// 重试前先刷新实体
|
||||
entityManager.refresh(findEntityById(id));
|
||||
@ -392,7 +395,7 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Class<T> getEntityClass() {
|
||||
public Class<T> getEntityClass() {
|
||||
Class<?>[] genericTypes = GenericTypeResolver.resolveTypeArguments(getClass(), BaseServiceImpl.class);
|
||||
if (genericTypes != null && genericTypes.length > 0) {
|
||||
return (Class<T>) genericTypes[0];
|
||||
@ -406,18 +409,4 @@ public abstract class BaseServiceImpl<T extends Entity<ID>, ID extends Number &
|
||||
return repository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(getEntityClass().getSimpleName(), id));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = false)
|
||||
public T createEntity(T entity) {
|
||||
return repository.save(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = false)
|
||||
public T updateEntity(T entity) {
|
||||
T currentEntity = findEntityById(entity.getId());
|
||||
currentEntity.checkVersion(entity.getVersion());
|
||||
return repository.save(entity);
|
||||
}
|
||||
}
|
||||
@ -1,17 +1,10 @@
|
||||
package com.qqchen.deploy.backend.repository;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.entity.Tenant;
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface ITenantRepository extends IBaseRepository<Tenant, Long> {
|
||||
|
||||
List<Tenant> findByDeletedFalseOrderById();
|
||||
|
||||
boolean existsByCodeAndDeletedFalse(String code);
|
||||
|
||||
boolean existsByNameAndDeletedFalse(String name);
|
||||
// 添加特定的查询方法
|
||||
}
|
||||
@ -1,27 +1,27 @@
|
||||
package com.qqchen.deploy.backend.repository;
|
||||
|
||||
|
||||
import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
import com.qqchen.deploy.backend.entity.UserRole;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@Repository
|
||||
public interface IUserRoleRepository extends IBaseRepository<UserRole, Long> {
|
||||
|
||||
@Query("SELECT ur FROM UserRole ur WHERE ur.userId = :userId")
|
||||
Set<UserRole> findByUserId(@Param("userId") Long userId);
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM UserRole ur WHERE ur.userId = :userId AND ur.roleId = :roleId")
|
||||
void deleteByUserIdAndRoleId(@Param("userId") Long userId, @Param("roleId") Long roleId);
|
||||
|
||||
|
||||
@Query("SELECT COUNT(ur) > 0 FROM UserRole ur WHERE ur.userId = :userId AND ur.roleId = :roleId")
|
||||
boolean existsByUserIdAndRoleId(@Param("userId") Long userId, @Param("roleId") Long roleId);
|
||||
|
||||
}
|
||||
//package com.qqchen.deploy.backend.repository;
|
||||
//
|
||||
//
|
||||
//import com.qqchen.deploy.backend.framework.repository.IBaseRepository;
|
||||
//import com.qqchen.deploy.backend.entity.UserRole;
|
||||
//import org.springframework.data.jpa.repository.Modifying;
|
||||
//import org.springframework.data.jpa.repository.Query;
|
||||
//import org.springframework.data.repository.query.Param;
|
||||
//import org.springframework.stereotype.Repository;
|
||||
//
|
||||
//import java.util.Set;
|
||||
//
|
||||
//@Repository
|
||||
//public interface IUserRoleRepository extends IBaseRepository<UserRole, Long> {
|
||||
//
|
||||
// @Query("SELECT ur FROM UserRole ur WHERE ur.userId = :userId")
|
||||
// Set<UserRole> findByUserId(@Param("userId") Long userId);
|
||||
//
|
||||
// @Modifying
|
||||
// @Query("DELETE FROM UserRole ur WHERE ur.userId = :userId AND ur.roleId = :roleId")
|
||||
// void deleteByUserIdAndRoleId(@Param("userId") Long userId, @Param("roleId") Long roleId);
|
||||
//
|
||||
//
|
||||
// @Query("SELECT COUNT(ur) > 0 FROM UserRole ur WHERE ur.userId = :userId AND ur.roleId = :roleId")
|
||||
// boolean existsByUserIdAndRoleId(@Param("userId") Long userId, @Param("roleId") Long roleId);
|
||||
//
|
||||
//}
|
||||
@ -2,9 +2,8 @@ package com.qqchen.deploy.backend.service;
|
||||
|
||||
import com.qqchen.deploy.backend.entity.Tenant;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import com.qqchen.deploy.backend.dto.request.TenantRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.TenantResponse;
|
||||
import com.qqchen.deploy.backend.dto.TenantDTO;
|
||||
|
||||
public interface ITenantService extends IBaseService<Tenant, Long, TenantRequest, TenantResponse> {
|
||||
public interface ITenantService extends IBaseService<Tenant, TenantDTO, Long> {
|
||||
// 添加租户特有的业务方法
|
||||
}
|
||||
@ -1,15 +1,20 @@
|
||||
package com.qqchen.deploy.backend.service;
|
||||
|
||||
import com.qqchen.deploy.backend.dto.UserDTO;
|
||||
import com.qqchen.deploy.backend.framework.service.IBaseService;
|
||||
import com.qqchen.deploy.backend.dto.request.LoginRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.LoginResponse;
|
||||
import com.qqchen.deploy.backend.entity.User;
|
||||
import com.qqchen.deploy.backend.dto.request.UserRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.UserResponse;
|
||||
import com.qqchen.deploy.backend.dto.RoleDTO;
|
||||
|
||||
public interface IUserService extends IBaseService<User, Long, UserRequest, UserResponse> {
|
||||
import java.util.List;
|
||||
|
||||
public interface IUserService extends IBaseService<User, UserDTO, Long> {
|
||||
LoginResponse login(LoginRequest request);
|
||||
UserResponse register(UserRequest request);
|
||||
UserDTO register(UserRequest request);
|
||||
boolean checkUsernameExists(String username);
|
||||
boolean checkEmailExists(String email);
|
||||
List<RoleDTO> getUserRoles(Long userId);
|
||||
List<RoleDTO> getCurrentUserRoles();
|
||||
}
|
||||
@ -1,19 +1,25 @@
|
||||
//package com.qqchen.deploy.backend.service.impl;
|
||||
//
|
||||
//import com.qqchen.deploy.backend.entity.Tenant;
|
||||
//import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
//import com.qqchen.deploy.backend.repository.TenantRepository;
|
||||
//import com.qqchen.deploy.backend.service.ITenantService;
|
||||
//import com.qqchen.deploy.backend.dto.request.TenantRequest;
|
||||
//import com.qqchen.deploy.backend.dto.response.TenantResponse;
|
||||
//import org.springframework.core.convert.ConversionService;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//
|
||||
//@Service
|
||||
//public class TenantServiceImpl extends BaseServiceImpl<Tenant, Long, TenantRequest, TenantResponse>
|
||||
// implements ITenantService {
|
||||
//
|
||||
// public TenantServiceImpl(TenantRepository repository, ConversionService conversionService) {
|
||||
// super(repository, conversionService);
|
||||
// }
|
||||
//}
|
||||
package com.qqchen.deploy.backend.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.entity.Tenant;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.qqchen.deploy.backend.repository.ITenantRepository;
|
||||
import com.qqchen.deploy.backend.service.ITenantService;
|
||||
import com.qqchen.deploy.backend.dto.TenantDTO;
|
||||
import com.qqchen.deploy.backend.converter.TenantConverter;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class TenantServiceImpl extends BaseServiceImpl<Tenant, TenantDTO, Long> implements ITenantService {
|
||||
|
||||
public TenantServiceImpl(ITenantRepository repository, TenantConverter converter) {
|
||||
super(repository, converter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TenantDTO> findAll(BaseQuery query) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -2,18 +2,23 @@ package com.qqchen.deploy.backend.service.impl;
|
||||
|
||||
import com.qqchen.deploy.backend.framework.enums.ResponseCode;
|
||||
import com.qqchen.deploy.backend.framework.exception.BusinessException;
|
||||
import com.qqchen.deploy.backend.framework.query.BaseQuery;
|
||||
import com.qqchen.deploy.backend.framework.security.SecurityUtils;
|
||||
import com.qqchen.deploy.backend.framework.security.util.JwtTokenUtil;
|
||||
import com.qqchen.deploy.backend.framework.service.impl.BaseServiceImpl;
|
||||
import com.qqchen.deploy.backend.framework.converter.ConversionService;
|
||||
import com.qqchen.deploy.backend.dto.request.LoginRequest;
|
||||
import com.qqchen.deploy.backend.dto.request.UserRequest;
|
||||
import com.qqchen.deploy.backend.dto.response.LoginResponse;
|
||||
import com.qqchen.deploy.backend.dto.response.UserResponse;
|
||||
import com.qqchen.deploy.backend.entity.User;
|
||||
import com.qqchen.deploy.backend.repository.IUserRepository;
|
||||
import com.qqchen.deploy.backend.service.IUserService;
|
||||
import com.qqchen.deploy.backend.converter.RoleConverter;
|
||||
import com.qqchen.deploy.backend.converter.UserConverter;
|
||||
import com.qqchen.deploy.backend.dto.UserDTO;
|
||||
import com.qqchen.deploy.backend.dto.RoleDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
@ -21,12 +26,15 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class UserServiceImpl extends BaseServiceImpl<User, Long, UserRequest, UserResponse>
|
||||
implements IUserService {
|
||||
public class UserServiceImpl extends BaseServiceImpl<User, UserDTO, Long> implements IUserService {
|
||||
|
||||
private final IUserRepository userRepository;
|
||||
private final UserConverter converter;
|
||||
private final RoleConverter roleConverter;
|
||||
|
||||
@Resource
|
||||
private AuthenticationManager authenticationManager;
|
||||
@ -34,14 +42,15 @@ public class UserServiceImpl extends BaseServiceImpl<User, Long, UserRequest, Us
|
||||
@Resource
|
||||
private JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
public UserServiceImpl(IUserRepository userRepository, ConversionService conversionService) {
|
||||
super(userRepository, conversionService);
|
||||
this.userRepository = userRepository;
|
||||
public UserServiceImpl(IUserRepository repository, UserConverter converter, RoleConverter roleConverter) {
|
||||
super(repository, converter);
|
||||
this.converter = converter;
|
||||
this.roleConverter = roleConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = false)
|
||||
public UserResponse register(UserRequest request) {
|
||||
public UserDTO register(UserRequest request) {
|
||||
if (checkUsernameExists(request.getUsername())) {
|
||||
throw new BusinessException(ResponseCode.USERNAME_EXISTS);
|
||||
}
|
||||
@ -49,43 +58,72 @@ public class UserServiceImpl extends BaseServiceImpl<User, Long, UserRequest, Us
|
||||
throw new BusinessException(ResponseCode.EMAIL_EXISTS);
|
||||
}
|
||||
|
||||
User user = conversionService.toEntity(request, User.class);
|
||||
User savedUser = createEntity(user);
|
||||
return conversionService.toResponse(savedUser);
|
||||
UserDTO userDTO = new UserDTO();
|
||||
userDTO.setUsername(request.getUsername());
|
||||
userDTO.setEmail(request.getEmail());
|
||||
userDTO.setNickname(request.getNickname());
|
||||
userDTO.setPhone(request.getPhone());
|
||||
|
||||
return create(userDTO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkUsernameExists(String username) {
|
||||
return userRepository.existsByUsername(username);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkEmailExists(String email) {
|
||||
return userRepository.existsByEmail(email);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public LoginResponse login(LoginRequest request) {
|
||||
Authentication authentication = authenticationManager.authenticate(
|
||||
new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
|
||||
);
|
||||
// Authentication authentication = authenticationManager.authenticate(
|
||||
// new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword())
|
||||
// );
|
||||
//
|
||||
// UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
// String token = jwtTokenUtil.generateToken(userDetails);
|
||||
//
|
||||
// User user = repository.findByUsernameAndDeletedFalse(userDetails.getUsername())
|
||||
// .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
|
||||
//
|
||||
// LoginResponse response = new LoginResponse();
|
||||
// response.setId(user.getId());
|
||||
// response.setUsername(user.getUsername());
|
||||
// response.setNickname(user.getNickname());
|
||||
// response.setEmail(user.getEmail());
|
||||
// response.setPhone(user.getPhone());
|
||||
// response.setToken(token);
|
||||
//
|
||||
// log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
|
||||
// return response;
|
||||
return null;
|
||||
}
|
||||
|
||||
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
|
||||
String token = jwtTokenUtil.generateToken(userDetails);
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<RoleDTO> getUserRoles(Long userId) {
|
||||
User user = findEntityById(userId);
|
||||
Hibernate.initialize(user.getRoles());
|
||||
return roleConverter.toDtoList(new ArrayList<>(user.getRoles()));
|
||||
}
|
||||
|
||||
User user = userRepository.findByUsernameAndDeletedFalse(userDetails.getUsername())
|
||||
.orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<RoleDTO> getCurrentUserRoles() {
|
||||
// String username = SecurityUtils.getCurrentUsername();
|
||||
// User user = repository.findByUsernameAndDeletedFalse(username)
|
||||
// .orElseThrow(() -> new BusinessException(ResponseCode.USER_NOT_FOUND));
|
||||
// Hibernate.initialize(user.getRoles());
|
||||
// return roleConverter.toDtoList(new ArrayList<>(user.getRoles()));
|
||||
return null;
|
||||
}
|
||||
|
||||
LoginResponse response = new LoginResponse();
|
||||
response.setId(user.getId());
|
||||
response.setUsername(user.getUsername());
|
||||
response.setNickname(user.getNickname());
|
||||
response.setEmail(user.getEmail());
|
||||
response.setPhone(user.getPhone());
|
||||
response.setToken(token);
|
||||
|
||||
log.info("用户 {} ({}) 登录成功", user.getUsername(), user.getNickname());
|
||||
return response;
|
||||
@Override
|
||||
public List<UserDTO> findAll(BaseQuery query) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user