我正在处理某种类型的缓存,有时我们需要根据last_access_date
将表修剪为500条记录(仅保留500条最近访问的行)。
使用“普通” SQL,可以使用以下方法完成:
DELETE FROM records WHERE id not in
(SELECT id FROM records ORDER BY last_access_date DESC LIMIT 500)
现在,由于JPQL中没有
LIMIT
或类似ROWNUM
的东西,所以我发现的唯一解决方案是在 native SQL中,这是次优的,因为我们在多个DBMS(至少是Oracle和MSSQL)上运行。另外,
setMaxResults()
(JPQLs版本的LIMIT
)对于DELETE
语句似乎无效。使用JPQL真的没有办法做到这一点吗?
最佳答案
您可以这样做:
String sql = "SELECT x.id FROM records x ORDER BY x.last_access_date DESC";
TypedQuery<Long> query = em.createQuery(sql, Long.class);
List<Long> ids = query.setMaxResults(500).getResultList();
String delete = "DELETE FROM records x where x.id not in :ids";
em.createQuery(delete).setParameter("ids", ids).executeUpdate();
我不记得删除查询的确切语法,因此您可能必须将
:ids
放在括号之间,例如:String delete = "DELETE FROM records x where x.id not in (:ids)";
编辑: dkb提出了一种关于注释的更快的解决方案(取决于唯一的日期以确保剩余行数的完美准确性):
String sql = "SELECT x.last_access_date FROM records x ORDER BY x.last_access_date DESC";
//If you're not using calendar, change to your specific date class
TypedQuery<Calendar> query = em.createQuery(sql, Calendar.class);
Calendar lastDate = query.setFirstResult(499).setMaxResults(1).getSingleResult();
String delete = "DELETE FROM records x where x.last_access_date < :lastDate";
em.createQuery(delete).setParameter("lastDate", lastDate, TemporalType.DATE).executeUpdate();