package com.kucun.Service;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;
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) {
try {
Map<String, Object> response = new HashMap<>();
Map<String, CustomRepository<?, ?>> repoMap = repositoryService.getRepositoryNameMap();
allData.forEach((key, entities) -> {
// 去掉末尾的's'以获取实体类型名
String entityName = key.substring(0, key.length() - 1);
CustomRepository<?, ?> repo = repoMap.get(entityName);
if (repo != null && entities != null && !entities.isEmpty()) {
try {
// 保存实体列表
List<?> savedEntities = repo.saveAll(entities);
response.put(key, savedEntities);
} catch (Exception e) {
response.put(key + "_error", "保存失败: " + e.getMessage());
}
}
});
return Information.NewSuccess(response);
} catch (Exception ex) {
return Information.Newfail(500, "保存全部数据失败: " + ex.getMessage(), null);
}
}
// ... existing code ...
}
// 添加保存全部数据的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());
}
}-------------package com.kucun.dataDo;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.Param;
import com.kucun.data.entity.Bancai;
import com.kucun.data.entity.Dingdan_bancai;
//修改后
@NoRepositoryBean
public interface CustomRepository<T, ID> extends JpaRepository<T, ID>{
// 符合命名规范
// 查询指定时间后的更新记录
List<T> findByLastUpdatedAfter(Date date);
// 查询指定时间后的删除记录
List<T> findByDeletedAtAfter(Date date);
// 查询指定时间后的所有变更(更新+删除)
@Query("SELECT e FROM #{#entityName} e WHERE " +
"e.lastUpdated > :since OR " +
"(e.deleted = true AND e.deletedAt > :since)")
List<T> findChangesSince(@Param("since") Date since);
}
package com.kucun.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.ResolvableType;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;
import com.kucun.dataDo.CustomRepository;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class DynamicRepositoryService {
@Autowired
private ApplicationContext applicationContext;
// 修改为存储 CustomRepository 类型
private final Map<String, CustomRepository<?, ?>> repositoryMap = new HashMap<>();
private final Map<Class<?>, CustomRepository<?, ?>> classRepositoryMap = new HashMap<>();
private final Map<String, Class<?>> stringClassMap = new HashMap<>();
@PostConstruct
public void init() {
// 关键修改:获取 CustomRepository 类型而非 JpaRepository
Map<String, CustomRepository> repositories =
applicationContext.getBeansOfType(CustomRepository.class);
repositories.forEach((beanName, repo) -> {
Class<?> entityClass = resolveEntityClass(repo);
if (entityClass != null) {
String simpleName = entityClass.getSimpleName().toLowerCase();
repositoryMap.put(simpleName, repo);
classRepositoryMap.put(entityClass, repo);
stringClassMap.put(simpleName, entityClass);
}
});
}
// 解析实体类的方法(保持不变)
private Class<?> resolveEntityClass(CustomRepository<?, ?> repository) {
ResolvableType repoType = ResolvableType.forClass(repository.getClass());
ResolvableType customRepoType = repoType.as(CustomRepository.class);
ResolvableType entityType = customRepoType.getGeneric(0);
return entityType.resolve();
}
// 修改返回类型为 CustomRepository
public CustomRepository<?, ?> getJpaRepository(String entityName) {
CustomRepository<?, ?> repo = repositoryMap.get(entityName.toLowerCase());
if (repo == null) {
throw new IllegalArgumentException("未找到实体 " + entityName + " 对应的Repository");
}
return repo;
}
// 修改返回类型为 CustomRepository
public CustomRepository<?, ?> getJpaRepository(Class<?> entityClass) {
CustomRepository<?, ?> repo = classRepositoryMap.get(entityClass);
if (repo == null) {
throw new IllegalArgumentException("未找到实体类 " + entityClass.getName() + " 对应的Repository");
}
return repo;
}
public Map<String, CustomRepository<?, ?>> getRepositoryNameMap() {
return repositoryMap;
}
// 使用 CustomRepository 直接调用自定义方法
public List<?> findUpdatedSince(String entityName, Date since) {
try {
CustomRepository<?, ?> repo = repositoryMap.get(entityName.toLowerCase());
return repo.findByLastUpdatedAfter(since);
} catch (Exception e) {
return Collections.emptyList();
}
}
// Getter 方法保持兼容性
public Map<String, Class<?>> getStringClassMap() {
return stringClassMap;
}
public Map<Class<?>, CustomRepository<?, ?>> getClassRepositoryMap() {
return classRepositoryMap;
}
}
The method saveAll(Iterable<S>) in the type JpaRepository<capture#59-of ?,capture#60-of ?> is not applicable for the arguments (List<capture#61-of ?>)Java(67108979)
<S> List<S> org.springframework.data.jpa.repository.JpaRepository.saveAll(Iterable<S> entities)
Saves all given entities.
Specified by: saveAll(...) in CrudRepository
Type Parameters:
Parameters:
entities must not be null nor must it contain null.
Returns:
the saved entities; will never be null. The returned Iterable will have the same size as the Iterable passed as an argument.
最新发布