一、问题描述
@PersistenceContext
private EntityManager entityManager;
public static Page getPageDate(String selectSql, String countSql, String whereSql, int page, int size,Class clazz){
//1、校验参数
if (StringUtils.isBlank(selectSql) || StringUtils.isBlank(countSql)) {
log.info("参数校验失败,参数{}{}为必填项", "selectSql", "countSql");
return null;
}
if (StringUtils.isNotBlank(whereSql)) {
countSql = countSql + whereSql;
log.info("执行sql >>>>>> {},获取数据总数", countSql);
selectSql = selectSql + whereSql;
log.info("执行sql >>>>>> {},获取数据", selectSql);
log.info(selectSql);
}
//2、数据查询逻辑
try{
//获取数据总数
Query countQuery = entityManagerPrimary.createNativeQuery(countSql);
BigInteger totalCount = (BigInteger)countQuery.getSingleResult();
//查询数据
Query query = entityManagerPrimary.createNativeQuery(selectSql, clazz);
//设置分页信息
Pageable pageable = new PageRequest(page - 1, size);
query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
List resultList = query.getResultList();
//查询结果封装
Page data = new PageImpl<>(resultList, pageable, totalCount.longValue());
return data;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
alterFlag属性与数据库中的值不一致。
二、原因查找
当使用`EntityManager.createNativeQuery()`方法执行原生SQL查询时,结果与数据库中的数据不一致可能是由于以下几个原因导致的:
1. 缓存的问题:JPA实现通常会使用缓存来提高性能,如果之前执行过相同的查询,并且缓存中存在数据,则可能会返回缓存中的数据而不是最新的数据库数据。你可以尝试在查询之前使用`EntityManager.clear()`方法清除缓存,或者使用`EntityManager.setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache)`提示来禁用缓存。
2. 事务问题:如果你在查询之前没有正确提交或回滚之前的事务,可能会导致查询结果不一致。你可以确保在执行查询之前提交或回滚任何未完成的事务,或者使用适当的事务隔离级别来解决并发读取的一致性问题。
3. 数据库同步问题:如果你的查询结果与数据库中的数据不一致,可能是因为数据库存在未及时同步的情况。你可以尝试手动执行`FLUSH`命令来将所有未保存的更改立即刷新到数据库中,以确保读取到最新的数据。
4. 缓存配置问题:某些情况下,JPA缓存的配置可能导致数据不一致。你可以检查缓存配置是否正确,并且缓存的过期策略是否满足你的需求。
5. 其他并发问题:如果在查询过程中存在其他并发操作修改了数据库中的数据,那么查询结果可能与数据库中的数据不一致。这种情况下,你可以考虑使用事务隔离级别来解决并发读取问题,或者使用乐观锁来处理并发修改。
综上所述,查询结果与数据库中的数据不一致可能是由于缓存、事务、数据库同步、缓存配置或其他并发问题引起的。你可以根据具体情况检查和调整相关配置,并考虑使用事务隔离级别或乐观锁来解决这个问题。
三、解决办法
@PersistenceContext
private EntityManager entityManager;
public static Page getPageDate(String selectSql, String countSql, String whereSql, int page, int size,Class clazz){
//1、校验参数
if (StringUtils.isBlank(selectSql) || StringUtils.isBlank(countSql)) {
log.info("参数校验失败,参数{}{}为必填项", "selectSql", "countSql");
return null;
}
if (StringUtils.isNotBlank(whereSql)) {
countSql = countSql + whereSql;
log.info("执行sql >>>>>> {},获取数据总数", countSql);
selectSql = selectSql + whereSql;
log.info("执行sql >>>>>> {},获取数据", selectSql);
log.info(selectSql);
}
//2、数据查询逻辑
try{
//清除缓存,防止缓存与数据库数据不一致问题
entityManagerPrimary.clear();
//获取数据总数
Query countQuery = entityManagerPrimary.createNativeQuery(countSql);
BigInteger totalCount = (BigInteger)countQuery.getSingleResult();
//查询数据
Query query = entityManagerPrimary.createNativeQuery(selectSql, clazz);
//设置分页信息
Pageable pageable = new PageRequest(page - 1, size);
query.setFirstResult(pageable.getOffset());
query.setMaxResults(pageable.getPageSize());
List resultList = query.getResultList();
//查询结果封装
Page data = new PageImpl<>(resultList, pageable, totalCount.longValue());
return data;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
使用 entityManager.clear()方法清楚缓存,问题解决。