package com.kucun.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kucun.Service.AppService;
import com.kucun.Service.DynamicRepositoryService;
import com.kucun.data.entity.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
@RestController
@RequestMapping("/app")
public class AppController {
@Autowired
private AppService appService;
@Autowired
private ObjectMapper objectMapper;
private Map<String, Class<?>> ENTITY_MAP ;
@Autowired
public AppController(
DynamicRepositoryService dynamicRepositoryService,
AppService appService,
ObjectMapper objectMapper
) {
this.ENTITY_MAP = dynamicRepositoryService.getStringClassMap();
this.appService = appService;
this.objectMapper = objectMapper;
}
// ====================== 数据查询 ======================
@GetMapping("/all")
public Information getAllData(
@RequestParam(value = "since",required=false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date since
) {
System.out.println("since:"+since);
try {
if(since == null)
return appService.getAllData();
else
return appService.getUpdatesSince(since);
} catch (Exception e) {
// TODO: handle exception
return Information.NewFail(e.getMessage());
}
}
// 添加保存全部数据的API端点
@PostMapping("/save-all")
public Information saveAllData(@RequestBody Map<String, List<?>> allData) {
try {
return appService.saveAllData(allData);
} catch (Exception e) {
return Information.NewFail("保存全部数据失败: " + e.getMessage());
}
}
@GetMapping("/all/{entityType}")
public Information getEntityData(@PathVariable String entityType,
@RequestParam(value = "since",required=false)
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date since) {
return appService.getEntityData(entityType.toLowerCase());
}
// ====================== CRUD操作 ======================
@PostMapping("/add/{entityType}")
public Information addEntity(
@PathVariable String entityType,
@RequestBody @Valid Map<String, Object> requestBody
) {
return handleEntityOperation(entityType, requestBody, "add");
}
@PostMapping("/select/{entityType}")
public Information queryEntity(
@PathVariable String entityType,
@RequestBody Map<String, Object> requestBody
) {
return handleEntityOperation(entityType, requestBody, "select");
}
@PostMapping("/delete/{entityType}")
public Information deleteEntity(
@PathVariable String entityType,
@RequestBody Map<String, Object> requestBody
) {
return handleEntityOperation(entityType, requestBody, "delete");
}
@PostMapping("/update/{entityType}")
public Information updateEntity(
@PathVariable String entityType,
@RequestBody Map<String, Object> requestBody
) {
return handleEntityOperation(entityType, requestBody, "update");
}
// ====================== 核心辅助方法 ======================
private Information handleEntityOperation(
String entityType,
Map<String, Object> requestBody,
String operation
) {
String normalizedType = entityType.toLowerCase();
// 特殊处理 Dingdan_bancai
if ("dingdan_bancai".equals(normalizedType)) {
try {
Dingdan_bancai entity = objectMapper.convertValue(requestBody, Dingdan_bancai.class);
// 从请求体中提取用户ID并设置到临时字段
if (requestBody.containsKey("currentUserId")) {
entity.setCurrentUserId(((Integer) requestBody.get("currentUserId")));
}
return appService.handleDingdanBancaiOperation( entity, operation);
} catch (Exception e) {
return Information.NewFail(operation + "操作失败: " + e.getMessage());
}
}
Class<?> entityClass = ENTITY_MAP.get(normalizedType);
if (entityClass == null) {
return Information.NewFail("不支持的实体类型: " + entityType);
}
try {
Object entity = objectMapper.convertValue(requestBody, entityClass);
//System.out.println(Information.NewSuccess(requestBody).DataJson());
switch (operation) {
case "add":
return appService.addEntity(entity);
case "select":
return appService.queryEntity((EntityBasis) entity);
case "delete":
// 确保实体实现了EntityBasis接口
if (entity instanceof EntityBasis) {
return appService.deleteEntity((EntityBasis) entity);
} else {
return Information.NewFail("删除操作需要实体实现EntityBasis接口");
}
case "update":
return appService.updateEntity(entity);
default:
return Information.NewFail("无效的操作类型");
}
} catch (Exception e) {
return Information.NewFail(operation + "操作失败: " + e.getMessage());
}
}
}package com.kucun.Service;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;
import javax.persistence.EntityNotFoundException;
import javax.transaction.Transactional;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import com.kucun.data.entity.*;
import com.kucun.dataDo.*;
/**
*
*
*
*/
@Service
public class AppService {
// 自动注入所有依赖
@Autowired private KucunRepository kucunRepository;
@Autowired private DynamicRepositoryService repositoryService;
@Autowired private EntityDependencyService dependencyService;
/**
* 获取所有实体类型的数据
* @return 包含所有实体数据的Map
*
*
*/
public Information getAllData() {
Map<String, Object> response = new HashMap<>();
repositoryService.getRepositoryNameMap().forEach((key, repo) ->
response.put(key + "s", repo.findAll())
);
return Information.NewSuccess(response);
}
/**
* 获取自指定时间以来的所有更新
* @param since 时间戳
* @return 按实体类型分组的更新数据
*/
public Information getUpdatesSince(Date since) {
Map<String, List<?>> updates = new HashMap<>();
Map<String, CustomRepository<?, ?>> repoMap = repositoryService.getRepositoryNameMap();
repoMap.forEach((entityName, repo) -> {
// 使用反射查询大于指定时间的记录
List<?> results = repositoryService.findUpdatedSince(entityName, since);
if (!results.isEmpty()) {
updates.put(entityName+'s', results);
}
});
return Information.NewSuccess(updates);
}
/**
* 获取指定实体类型的所有数据
* @param entityName 实体名称
* @return 实体数据列表
*
*
*/
public Information getEntityData(String entityName) {
JpaRepository<?, ?> repo = repositoryService.getJpaRepository(entityName);
return Information.NewSuccess(repo.findAll());
}
/**
* 添加新实体
* @param entity 要添加的实体对象
* @return 添加结果
*
*
*/
public Information addEntity(@Valid Object entity) {
try {
// 处理关联字段
handleAssociations(entity);
// 获取对应的Repository并保存
JpaRepository<Object, Serializable> repo =
(JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass());
//System.out.println(Information.NewSuccess(entity).DataJson());
if(entity instanceof User) {
if(((User) entity).getPass()!=null) {
String psass=((User) entity).getPass();
((User) entity).setPass(PasswordService.hashPassword(psass));
}
}
Object savedEntity = repo.save(entity);
// 如果是板材,初始化库存
if (savedEntity instanceof Bancai) {
initializeKucunForBancai((Bancai) savedEntity);
}
return Information.NewSuccess(savedEntity);
} catch (Exception ex) {
return Information.Newfail(500, "创建失败: " + ex.getMessage(), null);
}
}
/**
* 更新实体
* @param entity 包含ID的实体对象
* @return 更新结果
*
*
*/
public Information updateEntity(Object entity) {
if (entity == null) {
return Information.Newfail(403, "参数为空", null);
}
// 获取ID字段
Field idField=null;
try {
idField = getIdField(entity);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
idField.setAccessible(true);
Object idValue = idField.get(entity);
if (idValue == null) {
return Information.Newfail(403, "ID为空", null);
}
// 获取Repository和现有实体
JpaRepository<Object, Serializable> repo =
(JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entity.getClass());
Object existingEntity = repo.findById((Serializable) idValue)
.orElseThrow(() -> new RuntimeException("实体不存在"));
if(entity instanceof User) {
if(((User) entity).getPass()!=null) {
String psass=((User) entity).getPass();
((User) entity).setPass(PasswordService.hashPassword(psass));
}
}
// 复制非空属性并保存
copyNonNullProperties(entity, existingEntity);
return Information.NewSuccess(repo.save(existingEntity));
} catch (Exception ex) {
ex.fillInStackTrace();
return Information.Newfail(500, "更新失败: " + ex.getMessage(), null);
}
}
/**
* 删除实体
* @param entity 要删除的实体
* @return 删除结果
*/
public Information deleteEntity(EntityBasis entity) {
if (entity == null) {
return Information.NewFail("删除对象不能为空");
}
try {
String entityName = entity.getClass().getSimpleName().toLowerCase();
JpaRepository<Object, Serializable> repo =
(JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityName);
// 先加载完整实体(关键步骤)
Object managedEntity = repo.findById(entity.getId())
.orElseThrow(() -> new EntityNotFoundException("实体不存在"));
if(entity instanceof Bancai) {
Kucun k=kucunRepository.findByBancai((Bancai)entity);
if(k!=null&&k.getShuliang()>0) {
return Information.NewFail("库存不为零,无法删除");
}
if(k!=null) {
Field deletedField = k.getClass().getDeclaredField("deleted");
deletedField.setAccessible(true);
deletedField.set(k, true);
Field deletedAtField = k.getClass().getDeclaredField("deletedAt");
deletedAtField.setAccessible(true);
deletedAtField.set(k, new Date());
kucunRepository.save(k);
}
}
// 检查依赖关系
if (dependencyService.hasDependencies(entity.getClass(), entity.getId())) {
return Information.NewFail("该记录已被引用,无法删除");
}
// 使用实体对象删除(触发级联操作)
Field deletedField = managedEntity.getClass().getDeclaredField("deleted");
deletedField.setAccessible(true);
deletedField.set(managedEntity, true);
Field deletedAtField = managedEntity.getClass().getDeclaredField("deletedAt");
deletedAtField.setAccessible(true);
deletedAtField.set(managedEntity, new Date());
repo.save(managedEntity);
return Information.NewSuccess("删除成功");
} catch (Exception e) {
return Information.NewFail("删除错误: " + e.getMessage());
}
}/**
* 动态查询实体
* @param entity 包含查询条件的实体对象
* @return 查询结果
*/
public <T extends EntityBasis> Information queryEntity(T entity) {
if (entity == null) {
return Information.NewFail("查询参数不能为空");
}
try {
JpaRepository<T, ?> repo = (JpaRepository<T, ?>) repositoryService.getJpaRepository(entity.getClass());
// 创建基础查询条件
ExampleMatcher matcher = ExampleMatcher.matching()
.withIgnoreNullValues()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING);
if(entity.getDeleted()==null) {
// 添加软删除过滤条件
if (entity instanceof EntityBasis) {
// 动态设置deleted=false条件
Field deletedField = EntityBasis.class.getDeclaredField("deleted");
deletedField.setAccessible(true);
deletedField.set(entity, false);
}
}
Example<T> example = Example.of(entity, matcher);
return Information.NewSuccess(repo.findAll(example));
} catch (Exception e) {
return Information.NewFail("查询失败: " + e.getMessage());
}
}
// ====================== 私有辅助方法 ======================
/**
* 为板材初始化库存
* @param bancai 板材对象
*/
private void initializeKucunForBancai(Bancai bancai) throws Exception {
Kucun kucun = new Kucun(null, bancai, 0);
bancai.setKucun(kucunRepository.save(kucun));
}
/**
* 处理实体关联关系
* @param entity 要处理的实体
*/
private void handleAssociations(Object entity) throws Exception {
for (Field field : entity.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value = field.get(entity);
if (value == null) continue;
// 处理 JPA 实体关联
if (value instanceof EntityBasis) {
EntityBasis associated = (EntityBasis) value;
JpaRepository<Object, Serializable> repo =
(JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(associated.getClass().getSimpleName().toLowerCase());
// 只处理已存在实体(不创建新关联)
if (associated.getId() != null) {
Object managedEntity = repo.findById(associated.getId())
.orElseThrow(() -> new Exception("关联实体不存在"));
field.set(entity, managedEntity);
}
}
// 处理集合关联
else if (value instanceof Collection) {
List<Object> managedEntities = new ArrayList<>();
for (Object item : (Collection<?>) value) {
if (item instanceof EntityBasis) {
EntityBasis eb = (EntityBasis) item;
JpaRepository<Object, Serializable> repo =
(JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(eb.getClass().getSimpleName().toLowerCase());
if (eb.getId() != null) {
managedEntities.add(repo.findById(eb.getId())
.orElseThrow(() -> new Exception("关联实体不存在")));
}
}
}
if (!managedEntities.isEmpty()) {
field.set(entity, managedEntities);
}
}
}
}
/**
* 处理实体关联关系
* @param entity 要处理的实体
*/
private void handleAssociationss(Object entity) throws Exception {
for (Field field : entity.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value = field.get(entity);
if(value instanceof EntityBasis) {
}
}
}
/**
* 复制非空属性
* @param source 源对象
* @param target 目标对象
*/
private void copyNonNullProperties(Object source, Object target) throws IllegalAccessException {
for (Field field : source.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value = field.get(source);
// 跳过关联字段和ID字段
if (value != null &&
!(value instanceof EntityBasis) &&
!(value instanceof Collection) &&
!field.getName().equals("id")) {
try {
Field targetField = target.getClass().getDeclaredField(field.getName());
targetField.setAccessible(true);
targetField.set(target, value);
} catch (NoSuchFieldException ignored) {}
}
}
}
/*
* 获取实体类的id字段(支持父类查找)
* @param entity 实体对象
* @return Field对象或null
*/
public static Field getIdField(Object entity) {
if (entity == null) {
return null;
}
Class<?> clazz = entity.getClass();
// 递归查找类及其父类的id字段
while (clazz != null && clazz != Object.class) {
try {
Field idField = clazz.getDeclaredField("id");
idField.setAccessible(true);
return idField;
} catch (NoSuchFieldException e) {
// 继续向上查找父类
clazz = clazz.getSuperclass();
} catch (SecurityException e) {
e.printStackTrace();
return null;
}
}
return null;
}
// ====================== 专用方法处理 Dingdan_bancai ======================
@Transactional
public Information handleDingdanBancaiOperation(
Dingdan_bancai entity,
String operation
) {
try {
// 获取对应的Repository
JpaRepository<Object, Serializable> repo =
(JpaRepository<Object, Serializable>) repositoryService.getJpaRepository("dingdan_bancai");
switch (operation) {
case "add":
Dingdan_bancai savedEntity = (Dingdan_bancai) repo.save(entity);
updateKucunAndCreateJinhuo(savedEntity, savedEntity.getShuliang());
return Information.NewSuccess(savedEntity);
case "update":
// 先获取现有实体以计算差异
Dingdan_bancai existing = (Dingdan_bancai) repo.findById(entity.getId())
.orElseThrow(() -> new EntityNotFoundException("实体不存在"));
int quantityDifference = entity.getShuliang() - existing.getShuliang();
Dingdan_bancai updatedEntity = (Dingdan_bancai) repo.save(entity);
if (quantityDifference != 0) {
updateKucunAndCreateJinhuo(updatedEntity, quantityDifference);
}
return Information.NewSuccess(updatedEntity);
default:
return Information.NewFail("不支持的操作类型: " + operation);
}
} catch (Exception ex) {
return Information.NewFail(operation + "操作失败: " + ex.getMessage());
}
}
// 更新库存并创建进货记录
private void updateKucunAndCreateJinhuo(Dingdan_bancai db, int quantityChange) {
// 1. 更新库存
Bancai bancai = db.getBancai();
Kucun kucun = kucunRepository.findByBancai(bancai);
if (kucun == null) {
kucun = new Kucun(null, bancai, 0);
}
kucun.setShuliang(kucun.getShuliang() + quantityChange);
kucunRepository.save(kucun);
// 2. 创建进货记录
Jinhuo jinhuo = new Jinhuo();
jinhuo.setDingdan_bancai(db);
jinhuo.setShuliang(quantityChange);
jinhuo.setDate(new Date());
// 使用临时字段设置用户
if (db.getCurrentUserId() != null) {
User user = new User();
user.setId(db.getCurrentUserId());
jinhuo.setUser(user);
}
((JinhuoRepository)repositoryService.getJpaRepository(jinhuo.getClass())).save( jinhuo);
}
// ... existing code ...
/**
* 保存所有实体类型的数据
* @param allData 包含所有实体数据的Map,key为实体类型名+"s",value为实体列表
* @return 保存结果
*/
@Transactional
public Information saveAllData(Map<String, List<?>> allData) {
Map<String, Object> response = new HashMap<>();
allData.forEach((key, entities) -> {
String entityName = key.endsWith("s") ? key.substring(0, key.length() - 1) : key;
// 获取实体类类型
Class<?> entityClass = repositoryService.getEntityClass(entityName);
if (entityClass != null) {
// 类型安全转换
List<?> convertedList = entities.stream()
.filter(entityClass::isInstance)
.map(entityClass::cast)
.collect(Collectors.toList());
// 保存实体
List<?> savedEntities = repositoryService.saveEntities(
entityName,
convertedList
);
response.put(key, savedEntities);
} else {
response.put(key + "_error", "实体类型未注册");
}
});
return Information.NewSuccess(response);
}
// ... existing code ...
}@startuml
' 基础类与接口
abstract class EntityBasis {
+ Integer id
+ Date lastUpdated
+ Boolean deleted
+ Date deletedAt
+ getId()
+ setId(Integer)
}
interface EntityBasisId {
+ getId()
+ setId(Integer)
}
abstract class SimpleEntity {
+ Integer id
+ String name
}
' 实体类定义
class Mupi {
+ Boolean you
+ String name
+ List<Bancai> bancaisForMupi1
+ List<Bancai> bancaisForMupi2
}
class User {
+ String name
+ String andy
+ String pass
+ int role
+ int incumbency
}
class Chanpin_zujian {
+ Double one_howmany
+ Double zujianshu
}
class WechatUser {
+ String openid
+ String sessionKey
+ String nickname
+ String avatarUrl
+ String phoneNumber
+ Long userId
+ Date createTime
+ Integer status
}
class Kucun {
+ Integer shuliang
}
class Dingdan_chanpin {
+ Integer shuliang
}
class Information {
+ Integer Status
+ String text
+ Object data
}
class Zujian {
+ String name
+ List<Chanpin_zujian> chanping_zujian
}
class Dingdan_bancai {
+ Integer shuliang
+ Integer currentUserId
}
class Dingdan {
+ String number
+ Date xiadan
+ Date jiaohuo
+ List<Dingdan_chanpin> dingdan_chanpin
}
class Jinhuo {
+ Integer shuliang
+ Date date
+ String text
+ Integer theTypeOfOperation
}
class Caizhi {
+ String name
+ List<Bancai> bancai
}
class Bancai {
+ Double houdu
}
' 继承关系
EntityBasis --|> EntityBasisId
SimpleEntity --|> EntityBasisId
Mupi --|> EntityBasis
User --|> EntityBasis
Chanpin_zujian --|> EntityBasis
WechatUser --|> EntityBasis
Kucun --|> EntityBasis
Dingdan_chanpin --|> EntityBasis
Zujian --|> EntityBasis
Dingdan_bancai --|> EntityBasis
Dingdan --|> EntityBasis
Jinhuo --|> EntityBasis
Caizhi --|> EntityBasis
Bancai --|> EntityBasis
' 关联关系
' 一对一
Bancai -- Kucun : 1:1 (kucun)
' 一对多/多对一
Chanpin "1" -- "*" Chanpin_zujian : 包含 (chanpin_zujian)
Zujian "1" -- "*" Chanpin_zujian : 关联 (chanping_zujian)
Bancai "1" -- "*" Chanpin_zujian : 被使用 (bancai)
Dingdan "1" -- "*" Dingdan_chanpin : 包含 (dingdan_chanpin)
Chanpin "1" -- "*" Dingdan_chanpin : 被订购 (chanpin)
Dingdan "1" -- "*" Dingdan_bancai : 包含 (dingdan)
Chanpin "1" -- "*" Dingdan_bancai : 关联 (chanpin)
Zujian "1" -- "*" Dingdan_bancai : 关联 (zujian)
Bancai "1" -- "*" Dingdan_bancai : 被订购 (bancai)
User "1" -- "*" Jinhuo : 操作 (user)
Dingdan_bancai "1" -- "*" Jinhuo : 关联 (dingdan_bancai)
' 单向关联
WechatUser -- User : 绑定 (userId)
@enduml
用php脚本实现
最新发布