Hibernate创建产品时TransientPropertyValueException异常问题
解决Hibernate TransientPropertyValueException:关联未持久化Category实例问题
这个错误的核心原因很明确:你当前的代码直接把请求中的Category信息映射成了一个瞬态的CategoryEntity对象(也就是Hibernate没有跟踪它的持久化状态),而Hibernate在保存ProductEntity时,会尝试级联保存这个瞬态的Category——但实际上这个类别已经存在于数据库中,自然就抛出了异常。
解决方案步骤:
你需要先通过请求里的categoryKeyId从数据库中查询出已存在的CategoryEntity实例,再将它关联到ProductEntity上,而不是直接使用映射出来的瞬态对象。
修改后的服务层代码:
@Override public ProductDto createProduct(ProductDto productDto) { ProductDto returnValue = new ProductDto(); // 1. 检查产品名称是否已存在 if (productRepository.findByName(productDto.getName()) != null) throw new ApplicationServiceException("Record already in Database"); // 2. 通过categoryKeyId查询数据库中已存在的类别 CategoryEntity existingCategory = categoryRepository.findByCategoryKeyId(productDto.getCategory().getCategoryKeyId()); if (existingCategory == null) { throw new ApplicationServiceException("Category with provided categoryKeyId does not exist"); } ModelMapper modelMapper = new ModelMapper(); ProductEntity productEntity = modelMapper.map(productDto, ProductEntity.class); // 3. 将查询到的持久化类别实例关联到产品 productEntity.setCategory(existingCategory); String productKeyId = utils.generateProductKeyId(30); productEntity.setProductKeyId(productKeyId); ProductEntity storedProduct = productRepository.save(productEntity); returnValue = modelMapper.map(storedProduct, ProductDto.class); return returnValue; }
额外说明:
- 确保你的
CategoryRepository已经定义了findByCategoryKeyId(String categoryKeyId)方法,这是Spring Data JPA可以自动生成的查询方法,只要方法名符合规范即可。 - 为什么原来的代码不行?因为ModelMapper创建的CategoryEntity对象没有被Hibernate的Session管理,它的
id可能为null或者和数据库中的不一致,Hibernate会把它当作新对象处理,尝试插入,导致冲突。 - 如果你希望允许在创建产品时同时创建新类别(如果类别不存在),可以调整逻辑:当查询不到类别时,先保存这个CategoryEntity,再关联到产品——但这和你当前的需求不符,所以优先使用上述方案。
内容的提问来源于stack exchange,提问作者davidvera
相关产品推荐
相关产品推荐

