cannot be cast to java.io.Serializable

本文分享了在OA系统中实现员工管理模块的过程,重点介绍了如何解决“model.orgcannotbecasttojava.io.Serializable”错误,即确保部门对象实现Serializable接口以支持数据传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      前面三天一直在搞linux,因为初学,遇到的问题一大堆。系统重装了一遍又一遍,下了个wine装上去,然后用wine装上了学校的宽带认证客户端,装好的客户端又遇到了中文乱码的问题,至今仍未解决。最后索性装了宽带认证客户端的英文版,避开中文,可是,新的问题又出现了,这个用wine装的客户端运行的时候又报了一堆错误,崩溃,嗯,这个是我这几天说的频率最高的一句话。

 

扯远了。。。言归正传。。。(主要是发泄一下郁闷的情绪,调整一下心情。。)

 

今天开始继续写OA的组织管理和员工管理的模块!

 

组织机构的CRUD都已实现,今天来员工管理的CRUD,首先是员工列表的实现,传递的参数是员工所属部门的部门号或者id。

 

期间遇到这样一个问题"model.org cannot be cast to java.io.Serializable"

人家说得很清楚,org这个对象不能映射到java.io.Serializable,也就是说org必须实现serializable接口

 

 

由于部门org和员工person之间存在一些关系,员工的POJO持有部门的一个引用,而在在DAO层实现查找命令的时候,我需要用到person.org.id后者person.org.deptno(部门号),所以org这个对象必须实现序列化,以保证对象数据传递的完整性。

 

 

package com.kucun.Service; import java.io.Serializable; import java.lang.reflect.*; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.PluralAttribute; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; 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.Bancai; import com.kucun.data.entity.Caizhi; import com.kucun.data.entity.Chanpin; import com.kucun.data.entity.Chanpin_zujian; import com.kucun.data.entity.Dingdan; import com.kucun.data.entity.Dingdan_chanpin; import com.kucun.data.entity.Dingdan_chanpin_zujian; import com.kucun.data.entity.EntityBasis; import com.kucun.data.entity.Information; import com.kucun.data.entity.Kucun; import com.kucun.data.entity.Mupi; import com.kucun.data.entity.User; import com.kucun.data.entity.Zujian; import com.kucun.dataDo.BancaiRepository; import com.kucun.dataDo.CaizhiRepository; import com.kucun.dataDo.ChanpinRepository; import com.kucun.dataDo.ChanpinZujianRepository; import com.kucun.dataDo.DingdanChanpinRepository; import com.kucun.dataDo.DingdanChanpinZujianRepository; import com.kucun.dataDo.DingdanRepository; import com.kucun.dataDo.KucunRepository; import com.kucun.dataDo.MupiRepository; import com.kucun.dataDo.UserRepository; import com.kucun.dataDo.ZujianRepository; @Service public class AppService { // 注入所有需要的Repository @Autowired private CaizhiRepository caizhiRepository; @Autowired private BancaiRepository bancaiRepository; @Autowired private ChanpinRepository chanpinRepository; @Autowired private DingdanRepository dingdanRepository; @Autowired private MupiRepository mupiRepository; @Autowired private ZujianRepository zujianRepository; @Autowired private KucunRepository kucunRepository; @Autowired private UserRepository userRepository; @Autowired private ChanpinZujianRepository chanpinZujianRepository; @Autowired private DingdanChanpinZujianRepository dingdanChanpinZujianRepository; @Autowired private DingdanChanpinRepository dingdanChanpinRepository; @Autowired private DynamicRepositoryService repositoryService; // private Map<String, JpaRepository<?, ?>> shiti; // // // @Override // public void setApplicationContext(ApplicationContext context) { // this.shiti = getJpaRepositories(context); // } // // public Map<String, JpaRepository<?, ?>> getJpaRepositories(ApplicationContext context) { // return context.getBeansWithAnnotation(Repository.class) // .entrySet() // .stream() // .filter(entry -> entry.getValue() instanceof JpaRepository) // .collect(Collectors.toMap( // entry -> { // JpaRepository<?, ?> repo = (JpaRepository<?, ?>) entry.getValue(); // return getEntityClass(repo).getName(); // }, // entry -> (JpaRepository<?, ?>) entry.getValue() // )); // } // // public static Class<?> getEntityClass(JpaRepository<?, ?> repo) { // try { // // 处理Spring代理类 // Object target = repo; // while (target instanceof Advised) { // target = ((Advised) target).getTargetSource().getTarget(); // } // // // 通过Spring的ResolvableType解析泛型 // ResolvableType resolvableType = ResolvableType.forClass( // target.getClass()).as(JpaRepository.class); // // if (resolvableType.getGenerics().length > 0) { // Class<?> entityClass = resolvableType.getGeneric(0).resolve(); // if (entityClass != null) { // return entityClass; // } // } // // throw new IllegalStateException("无法解析实体类型"); // } catch (Exception e) { // throw new RuntimeException("获取实体类失败: " + e.getMessage(), e); // } // } // // public Information getAllDataWithChildIdse() { // Map<String, Object> response = new HashMap<>(); // // response.put("caizhis", (caizhiRepository.findAll())); // response.put("bancais", (bancaiRepository.findAll())); // response.put("chanpins", (chanpinRepository.findAll())); // response.put("dingdans", (dingdanRepository.findAll())); // response.put("mupis", (mupiRepository.findAll())); // response.put("zujians", (zujianRepository.findAll())); // response.put("kucuns", (kucunRepository.findAll())); // response.put("users", (userRepository.findAll())); // response.put("chanpin_zujians", (chanpinZujianRepository.findAll())); // response.put("chanpin_zujians", (dingdanChanpinZujianRepository.findAll())); // response.put("chanpin_zujians", (dingdanChanpinRepository.findAll())); // // return Information.NewSuccess(response); // } public Information getAllDataWithChildIdse() { Map<String, Object> response = new HashMap<>(); for (String key : repositoryService.getRepositoryNameMap().keySet()) { response.put(key+"s", (repositoryService.getJpaRepository(key).findAll())); } return Information.NewSuccess(response); } public Information getAllDataWithChildIdse(String e) { JpaRepository<?, ?> jp = repositoryService.getJpaRepository(e); System.out.println(jp); return Information.NewSuccess(jp.findAll()); } public Information getAddEntity(Object e) { Class<?> entityClass = e.getClass(); try { // 处理关联字段 handleAssociations(e); @SuppressWarnings("unchecked") JpaRepository<Object, Serializable> jp = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityClass); Object savedEntity = jp.save(e); if(savedEntity!=null) { if(savedEntity instanceof Bancai) { initializeKucunForBancai((Bancai)savedEntity); } } return Information.NewSuccess(savedEntity); } catch (Exception ex) { return Information.Newfail(500, "创建失败: " + ex.getMessage(), null); } } // 单独封装库存初始化方法 private void initializeKucunForBancai(Bancai bancai) throws Exception { Kucun kucun = new Kucun(null, bancai, 0); // 初始库存为0 try { bancai.setKucun(kucunRepository.save(kucun)); } catch (Exception e) { // TODO: handle exception throw new Exception("initializeKucunForBancai"+e); } } // 处理关联对象(转换为托管实体) private void handleAssociations(Object entity) throws Exception { Class<?> clazz = entity.getClass(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); Object value = field.get(entity); if (value == null) continue; // 处理单个关联实体 if (isEntityBasisField(field)) { EntityBasis associatedEntity = (EntityBasis) value; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(associatedEntity.getClass()); // 获取托管状态的关联实体 Object managedEntity = repo.findById(associatedEntity.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在")); field.set(entity, managedEntity); } // 处理集合关联 else if (isCollectionField(field)) { Collection<?> collection = (Collection<?>) value; List<Object> managedEntities = new ArrayList<>(); for (Object item : collection) { if (item instanceof EntityBasis) { EntityBasis eb = (EntityBasis) item; JpaRepository<Object, Serializable> repo = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(eb.getClass()); Object managedEntity = repo.findById(eb.getId()) .orElseThrow(() -> new RuntimeException("关联实体不存在")); managedEntities.add(managedEntity); } } // 更新集合为托管实体 if (!managedEntities.isEmpty()) { field.set(entity, managedEntities); } } } } /** * 更新 * @param e 实体待id * @return */ /** * 更新实体 * @param e 包含ID的实体 * @return 操作结果 */ public Information getupdateEntity(Object e) { if(e == null) { return Information.Newfail(403, "参数为空", null); } Class<?> entityClass = e.getClass(); try { Field idField = entityClass.getDeclaredField("id"); idField.setAccessible(true); Object idValue = idField.get(e); // 修正:应检查id是否为空,而不是不为空 if(idValue == null) { return Information.Newfail(403, "Id为空", null); } // 获取Repository @SuppressWarnings("unchecked") JpaRepository<Object, Serializable> jp = (JpaRepository<Object, Serializable>) repositoryService.getJpaRepository(entityClass); // 从数据库加载现有实体(托管状态) Object existingEntity = jp.findById((Serializable) idValue) .orElseThrow(() -> new RuntimeException("实体不存在")); // 复制属性(排除关联字段) copyNonNullProperties(e, existingEntity); // 保存托管状态的实体 Object updatedEntity = jp.save(existingEntity); return Information.NewSuccess(updatedEntity); } catch (Exception ex) { return Information.Newfail(500, "更新失败: " + ex.getMessage(), null); } } /** * 删除 * @param entity * @return */ public Information getdeleteEntity(EntityBasis entity) { Map<String, Object> response = new HashMap<>(); JpaRepository<Object, Integer> jp= (JpaRepository<Object, Integer>) repositoryService.getJpaRepository(entity.getClass().getSimpleName().toLowerCase()); if(!jp.existsById(entity.getId())) { return Information.NewFail("没有该数据"); } Object d=jp.findById(entity.getId()).orElse(null); for (Class<?> nt : repositoryService.getRepositoryMap().keySet()) { for (Field ent : nt.getDeclaredFields()) { if(ent.getClass().equals(entity.getClass())) { Object o=null; try { o = nt.newInstance(); ent.set(o, d); } catch (InstantiationException | IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(o); if(getSELECTEntity(o).getData()!=null) { return Information.NewFail("已在其他地方使用了,无法删除"); } } } } try { jp.deleteById(((EntityBasis)entity).getId()); } catch (Exception e) { // TODO: handle exception System.out.println(e.getLocalizedMessage()); } if(jp.existsById(entity.getId())) { System.out.println("删除失败"); return Information.NewFail("删除失败"); } return Information.NewSuccess(response); } // 复制非空属性(忽略关联字段) private void copyNonNullProperties(Object source, Object target) throws IllegalAccessException { Class<?> clazz = source.getClass(); for (Field field : clazz.getDeclaredFields()) { field.setAccessible(true); Object value = field.get(source); // 跳过关联字段和特殊字段 if (value != null && !isEntityBasisField(field) && !isCollectionField(field) && !field.getName().equals("id")) { Field targetField; try { targetField = target.getClass().getDeclaredField(field.getName()); targetField.setAccessible(true); targetField.set(target, value); } catch (NoSuchFieldException e) { // 忽略不存在的字段 } } } } // 检查是否为关联实体字段 private boolean isEntityBasisField(Field field) { return EntityBasis.class.isAssignableFrom(field.getType()); } // 检查是否为集合字段 private boolean isCollectionField(Field field) { return Collection.class.isAssignableFrom(field.getType()) || Map.class.isAssignableFrom(field.getType()); } /** * 根据非空属性值动态查询实体 * @param entity 包含查询条件的实体对象(非空属性作为查询条件) * @return 查询结果信息(成功时包含数据列表) */ public <T>Information getSELECTEntity(T entity) { if (entity == null) { return Information.NewFail("查询参数不能为空"); } Class<T> entityClass = (Class<T>) entity.getClass(); try { // 1. 获取非泛型的Repository JpaRepository repository = repositoryService.getJpaRepository(entityClass); // 2. 构建非泛型的Example查询 ExampleMatcher matcher = ExampleMatcher.matching() .withIgnoreNullValues() .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING); // 这里直接使用原始类型Example Example<T> example = Example.of(entity);//he type Example is not generic; it cannot be parameterized with arguments <T>the method of(T) is undefined for the type Example // 3. 执行查询 List<?> result = repository.findAll(example); return Information.NewSuccess(result); } catch (ClassCastException e) { return Information.NewFail("Repository类型不匹配: " + e.getMessage()); } catch (DataAccessException e) { return Information.NewFail("数据库访问错误: " + e.getMessage()); } catch (Exception e) { return Information.NewFail("系统错误: " + e.getMessage()); } } private List<Map<String, Object>> convertEntityBasis(List<EntityBasis> entities) { return entities.stream().map(entity -> { Map<String, Object> map = new HashMap<>(); Field[] fields = entity.getClass().getDeclaredFields(); try { // 添加实体自身的基本字段 map.put("id", entity.getId()); // 处理所有字段 for (Field field : fields) { field.setAccessible(true); // 允许访问私有字段 Object fieldValue = field.get(entity); if (fieldValue != null) { String fieldName = field.getName(); // 处理集合类型关联 if (isCollection(field)) { if (!((Collection<?>) fieldValue).isEmpty()) { List<Map<String, Object>> collectionItems = ((Collection<?>) fieldValue) .stream() .filter(item -> item instanceof EntityBasis) .map(item -> { Map<String, Object> itemMap = new HashMap<>(); itemMap.put("id", ((EntityBasis) item).getId()); return itemMap; }) .collect(Collectors.toList()); map.put(fieldName, collectionItems); } } // 处理单个实体关联 else if (implementsInterface(field, EntityBasis.class)) { Map<String, Object> associatedMap = new HashMap<>(); associatedMap.put("id", ((EntityBasis) fieldValue).getId()); map.put(fieldName, associatedMap); } // 处理其他基本类型字段 else if (!isSpecialField(fieldName)) { map.put(fieldName, fieldValue); } } } } catch (IllegalAccessException e) { e.printStackTrace(); } return map; }).collect(Collectors.toList()); } // 判断是否为特殊字段(需要排除的字段) private boolean isSpecialField(String fieldName) { return fieldName.equals("handler") || fieldName.equals("hibernateLazyInitializer"); } /** *-判断属性是否为集合类型 * @param field * @return */ boolean isCollection(Field field) { Class<?> type = field.getType(); // 检查是否为Java内置集合类型 if (Collection.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type) || type.isArray()) { return true; } // 检查是否实现集合相关接口(如Iterable) for (Class<?> interfaceType : type.getInterfaces()) { if (Iterable.class.isAssignableFrom(interfaceType)) { return true; } } return false; } /** * -判断属性是否实现特定接口 * @param field * @param targetInterface * @return */ boolean implementsInterface(Field field, Class<?> targetInterface) { Class<?> type = field.getType(); // 检查类本身是否实现接口 if (targetInterface.isAssignableFrom(type)) { return true; } // 检查实现的接口是否继承目标接口 for (Class<?> interfaceType : type.getInterfaces()) { if (targetInterface.isAssignableFrom(interfaceType)) { return true; } } return false; } private Object convertDingdanChanpins(List<Dingdan_chanpin> findAll) { // TODO Auto-generated method stub return null; } private Object convertDingdanChanpinZujians(List<Dingdan_chanpin_zujian> findAll) { // TODO Auto-generated method stub return null; } } 删除功能完善
最新发布
06-18
<think>我们主要关注删除功能的完善。原删除方法`getdeleteEntity`存在以下问题:1.依赖检查方式低效且不正确:通过反射遍历所有实体类的字段,判断字段类型是否与待删除实体类型相同,然后尝试实例化并设置字段值,再通过查询判断是否存在引用。-问题:这种方式无法准确判断关联关系(比如多对一、一对一等),且效率极低。2.删除后立即检查是否存在:在事务未提交的情况下,立即查询可能无法反映实际删除状态。3.异常处理不完善:捕获异常后仅打印,未返回错误信息。###改进方案我们将采用JPA的元模型(Metamodel)来检查实体是否被其他实体引用,即通过关联属性查询是否有其他实体引用了当前要删除的实体。###步骤1.注入`EntityManager`获取元模型。2.遍历所有实体类型,检查每个实体的关联属性(包括单值关联和集合关联)。3.对于每个关联属性,构建查询检查是否引用了待删除的实体。4.如果存在引用,则返回错误信息。5.如果不存在引用,则执行删除。###代码实现####1.添加依赖检查服务首先,我们创建一个服务类`EntityDependencyService`,用于检查实体是否被引用。```javaimportjavax.persistence.EntityManager;importjavax.persistence.PersistenceContext;importjavax.persistence.metamodel.EntityType;importjavax.persistence.metamodel.Metamodel;importjavax.persistence.metamodel.Attribute;importjavax.persistence.metamodel.PluralAttribute;importorg.springframework.stereotype.Service;importjava.util.Set;@ServicepublicclassEntityDependencyService{@PersistenceContextprivateEntityManagerentityManager;/***检查实体是否被其他实体引用*@paramentityClass待删除实体的类*@paramentityId待删除实体的ID*@return如果存在引用返回true,否则返回false*/public<T>booleanhasDependencies(Class<T>entityClass,ObjectentityId){Metamodelmetamodel=entityManager.getMetamodel();Set<EntityType<?>>entities=metamodel.getEntities();for(EntityType<?>entityType:entities){//跳过待删除实体本身(因为可能自关联)//检查该实体类型的每个关联属性for(Attribute<?,?>attr:entityType.getAttributes()){if(attr.isAssociation()){if(isReferencing(entityType,attr,entityClass,entityId)){returntrue;}}}}returnfalse;}/***判断某个实体的关联属性是否引用了目标实体*/private<T>booleanisReferencing(EntityType<?>entityType,Attribute<?,?>attribute,Class<T>targetEntityClass,ObjecttargetId){//获取关联的目标类型Class<?>targetType=attribute.getJavaType();//如果关联的目标类型不是待删除实体的类型,则跳过if(!targetEntityClass.isAssignableFrom(targetType)){returnfalse;}//构建查询:根据关联属性查询是否存在引用Stringjpql;if(attributeinstanceofPluralAttribute){//集合关联(一对多、多对多):MEMBEROFjpql=String.format("SELECTCOUNT(e)FROM%seWHERE:targetIdMEMBEROFe.%s",entityType.getName(),attribute.getName());}else{//单值关联(多对一、一对一):直接比较jpql=String.format("SELECTCOUNT(e)FROM%seWHEREe.%s.id=:targetId",entityType.getName(),attribute.getName());}Longcount=(Long)entityManager.createQuery(jpql).setParameter("targetId",targetId).getSingleResult();returncount>0;}}```####2.修改删除方法在`AppService`中注入`EntityDependencyService`,并重构`getdeleteEntity`方法。```java@ServicepublicclassAppService{//...其他注入@AutowiredprivateEntityDependencyServicedependencyService;publicInformationgetdeleteEntity(EntityBasisentity){StringentityName=entity.getClass().getSimpleName().toLowerCase();JpaRepository<Object,Integer>jp=(JpaRepository<Object,Integer>)repositoryService.getJpaRepository(entityName);if(!jp.existsById(entity.getId())){returnInformation.NewFail("没有该数据");}//检查是否存在依赖if(dependencyService.hasDependencies(entity.getClass(),entity.getId())){returnInformation.NewFail("已在其他地方使用了,无法删除");}try{jp.deleteById(entity.getId());//注意:在事务提交前,existsById可能仍返回true,所以这里不立即检查//而是通过捕获异常来判断是否删除成功returnInformation.NewSuccess("删除成功");}catch(Exceptione){//如果是因为外键约束导致的删除失败,这里会抛出异常returnInformation.NewFail("删除失败:"+e.getMessage());}}}```###说明1.**依赖检查**:使用JPA的元模型动态检查所有实体与待删除实体的关联关系,通过JPQL查询引用数量。2.**事务处理**:删除操作在事务中,删除后立即查询可能由于事务未提交而结果不准确,因此我们不再检查,而是通过捕获异常处理删除失败情况。3.**异常处理**:捕获删除过程中可能出现的异常(如外键约束违反),并返回友好提示。###注意事项-对于自关联的情况,需要特别处理(避免自己引用自己导致无法删除),但上述代码已经通过跳过自身关联属性检查(在`isReferencing`中,我们检查的是其他实体类型)避免了自关联的检查。但注意,自关联也可能需要检查(比如树形结构),这里我们暂时不考虑,因为自关联的检查可以通过在同一个实体类型内检查其他记录是否引用该记录来实现。如果需要支持自关联,可以在`hasDependencies`方法中不对当前实体类型跳过,而是同样检查其关联属性,但构建查询时要排除自身记录(避免删除时因为自引用而无法删除)。由于时间关系,我们暂不实现自关联检查,若有需要可后续扩展。###相关优化-**性能优化**:如果实体很多且关联复杂,全量检查可能性能较差。可以缓存元模型信息,或只检查已知可能引用的实体类型(通过配置)。-**批量删除**:如果需要批量删除,可以扩展方法,先检查所有待删除实体是否被引用,然后批量删除。###完整代码由于代码较长,这里只展示了关键部分。请将上述两个类添加到项目中,并修改`AppService`的删除方法。§§相关问题§§:1.如何实现JPA的软删除(逻辑删除)?2.在SpringDataJPA中如何高效地处理实体之间的级联删除?3.如何优化使用JPA元模型进行大量实体关联检查的性能?4.如何处理自关联实体的删除依赖检查?</think>### 动态实体删除功能的全面优化方案 您的删除功能存在几个关键问题需要解决: 1. **反射依赖检查效率低下**:遍历所有实体类的所有字段性能差 2. **类型判断不准确**:`ent.getClass().equals(entity.getClass())` 比较的是字段对象而非字段类型 3. **事务处理不当**:删除后立即查询可能受事务隔离级别影响 4. **错误处理不足**:异常信息未妥善处理 5. **关联检查不全面**:无法处理多级关联关系 以下是完整的优化方案: #### 1. 重构依赖检查服务 ```java import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.metamodel.*; import java.util.*; import java.util.stream.Collectors; @Service public class EntityDependencyService { @PersistenceContext private EntityManager entityManager; private final Map<Class<?>, Set<Attribute<?, ?>>> associationCache = new HashMap<>(); /** * 检查实体是否被其他实体引用 * @param entityClass 实体类 * @param entityId 实体ID * @return 存在引用返回true */ public boolean hasDependencies(Class<?> entityClass, Serializable entityId) { Metamodel metamodel = entityManager.getMetamodel(); Set<EntityType<?>> entities = metamodel.getEntities(); for (EntityType<?> entityType : entities) { // 跳过自身(避免自引用检查) if (entityType.getJavaType().equals(entityClass)) continue; Set<Attribute<?, ?>> associations = getAssociationAttributes(entityType); for (Attribute<?, ?> attr : associations) { if (attr.getJavaType().isAssignableFrom(entityClass)) { if (isReferenced(entityType, attr, entityId)) { return true; } } } } return false; } /** * 获取实体所有关联属性(带缓存) */ private Set<Attribute<?, ?>> getAssociationAttributes(EntityType<?> entityType) { return associationCache.computeIfAbsent(entityType.getJavaType(), k -> entityType.getAttributes().stream() .filter(Attribute::isAssociation) .collect(Collectors.toSet()) ); } /** * 检查特定关联是否引用目标实体 */ private boolean isReferenced(EntityType<?> entityType, Attribute<?, ?> attribute, Serializable targetId) { String jpql = buildReferenceQuery(entityType, attribute); Long count = (Long) entityManager.createQuery(jpql) .setParameter("targetId", targetId) .getSingleResult(); return count > 0; } /** * 构建引用检查查询 */ private String buildReferenceQuery(EntityType<?> entityType, Attribute<?, ?> attribute) { String entityName = entityType.getName(); String attrName = attribute.getName(); if (attribute instanceof PluralAttribute) { return String.format("SELECT COUNT(e) FROM %s e WHERE :targetId MEMBER OF e.%s", entityName, attrName); } else { return String.format("SELECT COUNT(e) FROM %s e WHERE e.%s.id = :targetId", entityName, attrName); } } } ``` #### 2. 重构删除服务 ```java @Service public class AppService { // 其他注入... @Autowired private EntityDependencyService dependencyService; public Information getdeleteEntity(EntityBasis entity) { String entityName = entity.getClass().getSimpleName().toLowerCase(); JpaRepository<Object, Serializable> jp = repositoryService.getJpaRepository(entityName); if (jp == null) { return Information.NewFail("未找到对应的Repository"); } if (!jp.existsById(entity.getId())) { return Information.NewFail("没有该数据"); } // 使用元模型检查依赖 if (dependencyService.hasDependencies(entity.getClass(), entity.getId())) { return Information.NewFail("已在其他地方使用,无法删除"); } try { // 获取实体(用于可能的级联删除) Object entityObj = jp.findById(entity.getId()).orElse(null); // 执行删除(带事务) deleteEntityWithCascade(jp, entityObj, entity.getClass()); // 延迟检查删除结果(避免事务隔离问题) return checkDeleteResult(jp, entity.getId()); } catch (Exception e) { return handleDeleteException(e); } } /** * 带级联处理的删除 */ @Transactional protected void deleteEntityWithCascade(JpaRepository<Object, Serializable> repo, Object entity, Class<?> entityClass) { // 特殊实体的级联处理 if (entity instanceof Bancai) { cascadeDeleteBancai((Bancai) entity); } else if (entity instanceof Chanpin) { cascadeDeleteChanpin((Chanpin) entity); } // 通用删除 repo.deleteById(entity.getId()); } /** * 删除板材的级联操作 */ private void cascadeDeleteBancai(Bancai bancai) { // 删除关联的库存记录 if (bancai.getKucun() != null) { kucunRepository.delete(bancai.getKucun()); } } /** * 删除产品的级联操作 */ private void cascadeDeleteChanpin(Chanpin chanpin) { // 删除关联的组件关系 List<Chanpin_zujian> relations = chanpinZujianRepository.findByChanpin(chanpin); chanpinZujianRepository.deleteAll(relations); } /** * 检查删除结果(延迟处理) */ private Information checkDeleteResult(JpaRepository<Object, Serializable> repo, Serializable id) { // 等待事务提交 try { Thread.sleep(100); // 简单延迟,生产环境应使用事务回调 } catch (InterruptedException ignored) {} boolean exists = repo.existsById(id); return exists ? Information.NewFail("删除失败") : Information.NewSuccess("删除成功"); } /** * 处理删除异常 */ private Information handleDeleteException(Exception e) { String message = e.getMessage(); // 处理外键约束错误 if (message.contains("foreign key constraint fails")) { return Information.NewFail("存在关联数据,无法删除"); } // 处理乐观锁错误 if (message.contains("OptimisticLockException")) { return Information.NewFail("数据已被修改,请刷新后重试"); } return Information.NewFail("删除失败: " + message); } } ``` #### 3. 增强 Repository 服务 ```java @Service public class DynamicRepositoryService { private final Map<String, JpaRepository<Object, Serializable>> repositoryMap = new ConcurrentHashMap<>(); /** * 注册实体对应的Repository */ public void registerRepository(Class<?> entityClass, JpaRepository<?, ?> repository) { String key = entityClass.getSimpleName().toLowerCase(); repositoryMap.put(key, (JpaRepository<Object, Serializable>) repository); } /** * 获取实体对应的Repository */ public JpaRepository<Object, Serializable> getJpaRepository(String entityName) { return repositoryMap.get(entityName.toLowerCase()); } /** * 获取实体对应的Repository */ public JpaRepository<Object, Serializable> getJpaRepository(Class<?> entityClass) { return getJpaRepository(entityClass.getSimpleName()); } } // 配置类自动注册Repository @Configuration public class RepositoryRegistryConfig { @Autowired private DynamicRepositoryService repoService; @Autowired private List<JpaRepository<?, ?>> repositories; @PostConstruct public void registerRepositories() { repositories.forEach(repo -> { Class<?> entityClass = resolveEntityClass(repo); if (entityClass != null) { repoService.registerRepository(entityClass, repo); } }); } private Class<?> resolveEntityClass(JpaRepository<?, ?> repo) { return Arrays.stream(repo.getClass().getGenericInterfaces()) .filter(ParameterizedType.class::isInstance) .map(ParameterizedType.class::cast) .filter(type -> type.getRawType().equals(JpaRepository.class)) .map(type -> (Class<?>) type.getActualTypeArguments()[0]) .findFirst() .orElse(null); } } ``` ### 关键优化点说明 1. **高效的关联检查** - 使用JPA元模型API获取所有实体关联关系 - 缓存关联属性减少元数据访问开销 - 动态构建JPQL查询检查引用 2. **级联删除支持** - 特殊实体(如Bancai、Chanpin)的定制级联逻辑 - 删除前清理关联数据避免约束错误 - 事务管理确保操作原子性 3. **健壮的错误处理** - 识别并处理常见数据库错误(外键约束、乐观锁) - 延迟检查删除结果解决事务隔离问题 - 友好的错误消息返回 4. **性能优化** - 缓存Repository映射关系 - 避免全量反射扫描实体字段 - 使用JPQL直接查询数据库计数 5. **可扩展设计** - 通过registerRepository动态添加新实体 - 级联删除逻辑可扩展 - 错误处理可定制 ### 使用示例 ```java // 在控制器中使用 @RestController @RequestMapping("/entities") public class EntityController { @Autowired private AppService appService; @DeleteMapping("/{entityType}/{id}") public ResponseEntity<Information> deleteEntity( @PathVariable String entityType, @PathVariable Integer id ) { // 创建实体实例 Class<?> entityClass = resolveEntityClass(entityType); EntityBasis entity = (EntityBasis) entityClass.newInstance(); entity.setId(id); // 执行删除 Information result = appService.getdeleteEntity(entity); return ResponseEntity.status(result.isSuccess() ? 200 : 400) .body(result); } private Class<?> resolveEntityClass(String entityType) { // 根据entityType解析实体类 // 示例:return Class.forName("com.kucun.data.entity." + entityType); } } ``` ### 高级优化:软删除支持 ```java // 实体基类添加删除标记 @MappedSuperclass public abstract class SoftDeletableEntity implements EntityBasis { @Column(name = "deleted", columnDefinition = "BOOLEAN DEFAULT false") private boolean deleted = false; // getter/setter } // 删除方法支持软删除 public Information getdeleteEntity(EntityBasis entity) { // ... if (entity instanceof SoftDeletableEntity) { SoftDeletableEntity softEntity = (SoftDeletableEntity) entity; softEntity.setDeleted(true); jp.save(softEntity); return Information.NewSuccess("标记删除成功"); } else { // 物理删除逻辑 } } // 查询过滤已删除记录 public interface SoftDeleteRepository<T extends SoftDeletableEntity> extends JpaRepository<T, Serializable> { @Query("SELECT e FROM #{#entityName} e WHERE e.deleted = false") List<T> findAllActive(); @Query("SELECT e FROM #{#entityName} e WHERE e.deleted = true") List<T> findAllDeleted(); } ``` ### 性能优化技巧 1. **批量删除优化** ```java @Transactional public void batchDelete(Class<?> entityClass, List<Serializable> ids) { // 检查依赖 boolean hasDeps = ids.stream().anyMatch(id -> dependencyService.hasDependencies(entityClass, id)); if (!hasDeps) { JpaRepository<Object, Serializable> repo = repoService.getJpaRepository(entityClass); repo.deleteAllById(ids); } } ``` 2. **异步删除** ```java @Async @Transactional public void asyncDelete(EntityBasis entity) { getdeleteEntity(entity); } ``` 3. **缓存优化** ```java @Cacheable(value = "entityDependencies", key = "#entityClass.name + '-' + #entityId") public boolean hasDependencies(Class<?> entityClass, Serializable entityId) { // 原始实现 } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值