You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate中session.remove()未删实体但session.get()返回null问题

问题描述

操作步骤:

  • 调用session.get(User.class, 11)从数据库获取User实体;
  • 调用session.remove(user)将实体标记为待删除(此时Hibernate尚未向数据库发送DELETE请求,实体仍存在于数据库和一级缓存persistenceContext中);
  • 再次调用session.get(User.class, 11)却返回null。

疑问:既然该实体仍存在于数据库和一级缓存中,为什么会返回null?

主类代码

public static void main(String[] args) {
    SessionFactory sessionFactory = HiberUtil.getSessionFactory();
    Session session = sessionFactory.openSession();

    session.beginTransaction();

    User user = session.get(User.class, 11);  <--- 非null
    session.remove(user);
    user = session.get(User.class, 11);       <--- null

    session.getTransaction().commit();
}

User实体类代码

@NoArgsConstructor
@AllArgsConstructor
@Builder
@jakarta.persistence.Entity
@Table(name = "Users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Getter
    private Long id;

    @Column(unique = true)
    private String userName;

    @Embedded
    private PersonalInfo personalInfo;

    @Enumerated(EnumType.STRING)
    private Role role;

    @Setter
    @Getter
    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "company_id")
    private Company company;
}
解答

这是Hibernate的预期行为,核心原因在于一级缓存(持久化上下文)会追踪实体的状态:

  1. 调用session.remove(user)时,Hibernate会把该实体的状态从「持久化」改为「待删除」,但仍将它保留在持久化上下文中;
  2. 再次调用session.get(User.class, 11)时,Hibernate会先检查一级缓存:
    • 如果找到状态为「待删除」的实体,不会返回该实体,而是直接返回null;
    • 这是Hibernate为了保证持久化上下文的状态一致性——既然实体已经被标记为待删除,就不能再被当作有效实体返回;
  3. 此时数据库里的记录确实还存在,但Hibernate优先以持久化上下文的状态为准,不会去数据库重新查询(除非调用session.refresh()或清除缓存)。

简单来说:一级缓存里确实有这个实体,但它的状态是待删除,Hibernate判定它已经「无效」,所以get方法返回null。直到事务提交时,Hibernate才会向数据库发送DELETE请求,真正删除这条记录。

内容的提问来源于stack exchange,提问作者Vsevolod IV

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 13:43:20