org.hibernate.ObjectNotFoundException: No row with the given identifier exists

本文探讨了Hibernate在处理外键关系时可能出现的问题及解决方案。主要分析了当对象B被删除后,若对象A仍保留其外键引用时,Hibernate如何进行处理。文中介绍了通过配置@OneToOne(fetch=FetchType.LAZY)及not-found属性来避免异常的方法。
问题产生原因:
有一个对象A,关联了对象B ,关联关系可以使 ManyToOne,On
eToOne 等,如果我们在数据库中清除了B对象,但是B对象还在A表中存在外键,这时候Hibernate检查这个关系的时候,会报出这个异常。但是A与B在数据库 为范围内不能耦合过紧,只能pojo中建立关联关系,此时要注意,清除A表中的外键,可以解决此问题,一般的垃圾数据会造成业务系统不能正常运转。

第二个原因:
查询的时候,假设对象A与B有着一对一的关系,一般我们配置
@On
eToOne
@JoinColumn(name = "xxx"),如果B被删除了,但是A中还维护这个外键关系
要配置
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "xxx")
的模式,不知道为什么默认不是lazy的,还要配置一下fetch = FetchType.LAZY

本要急于测试所以直接设置为不关联not-found="ignore"
Hibernate的many-to-one的元素的一个属性:not-found今天看Hibernate Reference,看到多对一关系时,看到mant-to-one元素有一个属性:not-found。用来指定引用的外键不存在时将如何处理:
  • exception(默认)抛出异常
  • ignore 忽略

以前不知道有这个属性,Hibernate就采用默认的抛出异常来处理了。经常出现显示一个项目的列表时没有数据。


<think>嗯,用户遇到了HibernateObjectRetrievalFailureException异常,提示没有指定ID的行存在。我需要帮他解决这个问题。首先,我得回忆一下这个异常通常是什么原因引起的。Hibernate在尝试通过主键加载一个对象时,如果在数据库里找不到对应的记录,就会抛出这个异常。常见的情况可能是数据被删除,或者关联实体不存在。 然后,我应该考虑可能的解决方案。首先,用户应该在调用get()或load()方法获取对象之前,先检查该ID是否存在。或者使用Hibernate的get()方法,因为get()会立即返回null,而load()可能会延迟抛出异常,导致问题出现在后续操作中,这样更难追踪。 另外,关联实体的问题也是一个常见原因。比如,如果实体A关联了实体B,而实体B的ID在数据库里不存在,这时候保存或加载实体A就会出错。这时候需要检查外键约束,确保所有关联的实体都存在。 还有,事务管理的问题。如果事务没有正确提交,可能导致数据未持久化,进而查询不到。需要检查事务是否在适当的地方提交了。 然后,异常处理方面,建议用户使用try-catch块捕获这个异常,并转换为更有意义的业务异常,或者友好的错误信息返回给前端。 接下来,用户可能需要生成相关问题,比如如何防止这种情况,或者关联实体的问题如何解决,或者Hibernate的get和load方法的区别,以及事务管理的最佳实践。这些都能帮助用户更全面地理解和解决问题。 还要注意用户提供的引用内容,不过看起来引用是关于Go语言map和HDF5存储的,可能和当前问题无关,所以可能不需要参考这部分内容。主要基于Hibernate的知识来解答。 最后,确保回答结构清晰,分点说明原因和解决方案,并给出示例代码,比如使用get()方法替代load(),检查关联实体存在性等。同时提醒用户处理事务和进行输入验证,避免无效ID的传递。</think>针对HibernateObjectRetrievalFailureException异常中"$No\ row\ with\ given\ identifier\ exists$"问题的解决方案如下: ### 原因分析 1. **数据不一致**:尝试访问的实体ID在数据库中不存在 2. **级联操作异常**:关联实体未正确级联保存/删除 3. **事务边界问题**:事务未提交导致数据不可见 4. **缓存不一致**:二级缓存中存在过时数据[^1] ### 解决方案 #### 1. 预验证存在性 ```java // 使用get()代替load()避免延迟异常 MyEntity entity = session.get(MyEntity.class, id); if (entity == null) { throw new EntityNotFoundException("ID " + id + " not found"); } ``` #### 2. 处理关联实体 对于外键关联实体,建议添加级联验证: ```java @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "foreign_key_id") @NotFound(action = NotFoundAction.IGNORE) // 忽略不存在的外键 private ForeignEntity foreignEntity; ``` #### 3. 事务优化 确保操作在事务边界内完成: ```java @Transactional public MyEntity getEntity(Long id) { return entityRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException(id)); } ``` #### 4. 缓存处理策略 在配置文件中添加: ```xml <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <property name="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</property> ``` ### 异常处理建议 ```java try { return session.load(MyEntity.class, id); } catch (ObjectNotFoundException ex) { throw new CustomBusinessException("请求的资源不存在", ex); } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Fighter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值