使用JPA CriteriaDelete结合子查询IN表达式删除数据未生效
使用CriteriaBuilder和CriteriaDelete删除关联实体数据的正确写法
你的代码存在几个关键问题导致删除操作无效果:
- CriteriaDelete不能同时关联两个实体根:
criteriaDelete.from()只能调用一次,关联要删除的实体类型,不能同时添加另一个关联实体的根。 - 未执行更新操作:创建查询后没有调用
executeUpdate()方法触发删除执行。 - IN条件写法错误:你用
deleteRoot.in(...)是把整个实体对象作为匹配条件,应该指定删除实体中与关联实体对应的字段(比如关联ID)来匹配子查询结果。
修正后的代码示例
// 1. 创建CriteriaDelete和要删除实体的根 CriteriaDelete<Y> criteriaDelete = criteriaBuilder.createCriteriaDelete(Y.class); Root<Y> deleteRoot = criteriaDelete.from(Y.class); // 2. 创建子查询,查询关联实体的目标字段(比如关联ID) Subquery<Long> subquery = criteriaDelete.subquery(Long.class); Root<T> queryRoot = subquery.from(T.class); subquery.select(queryRoot.get(key)); // key是关联实体中与Y实体匹配的字段,比如"relatedId" subquery.where(queryRoot.get("id").in(givenList)); // 3. 设置删除条件:Y实体的对应字段在子查询结果中 criteriaDelete.where(deleteRoot.get("关联字段名").in(subquery)); // 4. 执行删除操作,获取受影响行数 int affectedRows = entityManager.createQuery(criteriaDelete).executeUpdate();
关键说明
- 用
subquery替代先查询结果再传入的方式,这样会生成一条带子查询的DELETE语句,更高效且避免数据不一致。 - 确保
deleteRoot.get("关联字段名")是Y实体中存储T实体关联ID的字段,和子查询返回的字段类型一致。 - 必须调用
executeUpdate()才会实际执行删除操作,返回值为受影响的行数,可以用来验证是否删除成功。
内容的提问来源于stack exchange,提问作者Liam
相关产品推荐
相关产品推荐

