Files
notes/work/移动杭研/问题处理/2024-05/0506-域名配置需求工单计费字段问题.md
2026-03-01 01:43:46 +08:00

4.8 KiB
Raw Permalink Blame History

日期, 来源
日期 来源
2024-05-06 11:19 鹏豪

问题详情

域名配置需求计费字段刷新异常

处理过程

问题已复现。

标记位刷新地方:

com.cmcc.cdn.platform.selfservice.service.impl.BBossAndDssInteractiveServiceImpl#startCommercialCDR

首先怀疑是外层的大事务导致的后边去掉事务后依旧存在此问题。

逐步分析后发现是其后方存在一个实体查询存储逻辑。

应该是 JPA 的一级缓存问题了。

总结

selfServiceDomainConfigDao.setChargeFlagAndChargeTime() 方法更新了数据库中的值,但是后续通过 selfServiceDomainConfigDao.findByDomain() 方法查询时,返回的结果不是更新后的值。这可能是由于缓存导致的。您可以尝试以下解决方案:

  1. 清除缓存:在更新操作后,可以手动清除缓存,以确保后续查询操作能够获取到最新的数据。您可以在更新方法后添加一行代码来清除缓存,如下所示:

    selfServiceDomainConfigDao.setChargeFlagAndChargeTime(DomainChargeProcessEnum.SUCCESS.getIndex(), chargeTime, domain);
    entityManager.clear(); // 清除缓存
    
  2. 更新操作后延迟查询:为了避免缓存导致的数据不一致,您可以在更新操作后加入一段延迟,然后再进行查询操作。例如,您可以在更新后等待几毫秒后再进行查询操作,如下所示:

    selfServiceDomainConfigDao.setChargeFlagAndChargeTime(DomainChargeProcessEnum.SUCCESS.getIndex(), chargeTime, domain);
    Thread.sleep(100); // 延迟100毫秒
    Optional<SelfServiceDomainConfigPO> daoByDomain = selfServiceDomainConfigDao.findByDomain(speedDomain.getDomain());
    

请注意,这些解决方案仅适用于缓存引起的数据不一致问题。如果问题仍然存在,可能需要进一步检查代码逻辑或数据库事务设置。

在 Spring Data JPA 中,EntityManager 是 JPA 的核心类,用于实体的创建、查询、更新和删除操作。如果您在使用 Spring 框架,可以通过依赖注入(DI)的方式获取 EntityManager 的实例。这里有一个简单的示例说明如何在您的 Repository 或 Service 中注入 EntityManager

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Service
public class YourService {

    @PersistenceContext
    private EntityManager entityManager;

    public void yourMethod() {
        selfServiceDomainConfigDao.setChargeFlagAndChargeTime(DomainChargeProcessEnum.SUCCESS.getIndex(), chargeTime, domain);
        entityManager.clear(); // 使用EntityManager清除一级缓存
        // 其他逻辑...
    }
}

在这个例子中,我们使用了 @PersistenceContext 注解来自动注入 EntityManager。这样,您就可以在需要的时候调用 entityManager.clear() 来清除 JPA 的一级缓存。

请注意,直接操作 EntityManager 是比较低级的操作,通常我们希望尽量避免直接使用它,除非在处理复杂的业务逻辑或性能优化时确实需要。在大多数情况下,Spring Data JPA 提供的接口已经足够满足常规的数据访问需求。

entityManager.refresh(po)entityManager.clear() 在 JPA 中都用于管理实体和缓存,但它们的用途和影响是不同的:

  1. entityManager.refresh(po):

    • 这个方法用于从数据库中重新读取实体的当前状态,并刷新缓存中的实体对象。如果实体在数据库中被外部修改(例如,通过其他应用或直接在数据库中修改),使用 refresh() 可以确保您的实体状态与数据库保持一致。
    • 使用 refresh() 方法时,您需要传递一个特定的实体对象作为参数。这个方法只影响传递的实体对象,不会影响持久化上下文中的其他实体。
  2. entityManager.clear():

    • clear() 方法用于清除持久化上下文中的所有缓存。这意味着所有被管理的实体都会从持久化上下文中移除,之后的任何操作都需要重新从数据库中加载实体。
    • 使用 clear() 可以帮助避免内存泄漏,特别是在处理大量数据时。它也有助于确保数据的一致性,因为它强制应用从数据库重新加载实体数据,而不是使用可能已经过时的缓存数据。

总结来说,refresh() 是针对单个实体的局部刷新操作,而 clear() 是对整个持久化上下文的全局清除操作。选择使用哪一个取决于您的具体需求:如果需要更新特定实体的状态,使用 refresh();如果需要重置整个持久化上下文,使用 clear()