Hibernate 6.4如何绕过@SoftDelete限制查询所有记录?
解决Hibernate @SoftDelete下查询所有记录(含已删除)的方案
当你用Hibernate的@SoftDelete注解后,框架会自动给所有查询追加deleted = false的过滤条件,要绕过这个限制,有以下几种可行方法:
1. 自定义可开关的Filter覆盖默认软删除规则
Hibernate的软删除是通过内置Filter实现的,你可以在实体类上定义一个自定义Filter,手动控制是否包含已删除记录:
@Entity @SoftDelete(columnName = "deleted") @FilterDef(name = "includeDeleted", parameters = @ParamDef(name = "includeDeleted", type = Boolean.class)) @Filter( name = "includeDeleted", condition = "deleted = :includeDeleted OR :includeDeleted = TRUE" ) public class YourEntity { // 实体字段、getter/setter... }
查询时启用这个Filter并传入true参数:
Session session = entityManager.unwrap(Session.class); // 启用Filter,设置包含已删除记录 session.enableFilter("includeDeleted").setParameter("includeDeleted", true); // 执行查询,此时会返回所有记录(含已删除) List<YourEntity> allRecords = session.createQuery("FROM YourEntity", YourEntity.class).list(); // 可选:查询完成后关闭Filter,避免影响后续默认查询 session.disableFilter("includeDeleted");
2. 用原生SQL直接查询(完全绕过Hibernate过滤)
如果之前用原生SQL还是被加条件,大概率是因为你关联了实体类导致Hibernate介入。试试直接返回原生结果集,手动转换:
String sql = "SELECT id, name, deleted FROM your_entity"; List<Object[]> rawResults = entityManager.createNativeQuery(sql).getResultList(); // 手动映射为实体对象 List<YourEntity> allRecords = rawResults.stream() .map(row -> { YourEntity entity = new YourEntity(); entity.setId((Long) row[0]); entity.setName((String) row[1]); entity.setDeleted((Boolean) row[2]); return entity; }) .collect(Collectors.toList());
3. 禁用Hibernate的软删除Filter(依赖Hibernate API)
通过EntityManager获取Hibernate原生Query对象,直接关闭软删除过滤:
javax.persistence.Query jpaQuery = entityManager.createQuery("SELECT e FROM YourEntity e"); org.hibernate.query.Query hibernateQuery = jpaQuery.unwrap(org.hibernate.query.Query.class); // 关闭软删除的内置Filter hibernateQuery.setHibernateFilter("softDelete", false); List<YourEntity> allRecords = hibernateQuery.getResultList();
注意:这个方法直接依赖Hibernate私有API,项目如果切换JPA实现会失效,适合纯Hibernate项目。
4. 创建无软删除的视图实体(适合频繁查询场景)
如果业务中经常需要查全量数据,可以给原表创建一个数据库视图,然后创建对应视图的实体类(不加@SoftDelete):
- 先建数据库视图:
CREATE VIEW your_entity_full AS SELECT * FROM your_entity;
- 创建视图对应的实体:
@Entity @Table(name = "your_entity_full") public class YourEntityFull { @Id private Long id; private String name; private Boolean deleted; // getter/setter... }
- 查询这个实体就能直接获取所有记录:
List<YourEntityFull> allRecords = entityManager.createQuery("FROM YourEntityFull", YourEntityFull.class).getResultList();
内容的提问来源于stack exchange,提问作者Nipuna Perera
相关产品推荐
相关产品推荐

