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

88 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
日期: 2024-05-06 11:19
来源: 鹏豪
---
# 问题详情
域名配置需求计费字段刷新异常
# 处理过程
问题已复现。
标记位刷新地方:
com.cmcc.cdn.platform.selfservice.service.impl.BBossAndDssInteractiveServiceImpl#startCommercialCDR
![](../../../../attachment/images-paste/image-20240506144955056.png)
![](../../../../attachment/images-paste/image-20240506145003481.png)
![](../../../../attachment/images-paste/image-20240506145012447.png)
首先怀疑是外层的大事务导致的后边去掉事务后依旧存在此问题。
逐步分析后发现是其后方存在一个实体查询存储逻辑。
![](../../../../attachment/images-paste/image-20240506145452903.png)
应该是 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`
```java
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()`。