gpt4 book ai didi

java - 从 Hibernate persistenceContext 缓存中排除 JPA 实体?

转载 作者:行者123 更新时间:2023-12-02 04:47:59 26 4
gpt4 key购买 nike

我正在使用 Spring 构建一个 Web 应用程序,并使用 Hibernate 4.3.6 支持的 JPA 来实现持久性。一些背景:作业结果存储在存储库中,并且 ResultsController 对它们进行检查。前端使用长轮询,因此 ResultsController 创建一个 DeferredResult 对象,然后派生一个线程定期检查作业是否完成,以便填充延迟结果并触发响应。

private DeferredResultsResponse getResults(String idString, String runType, boolean returnOnNotDone) {
String userId = userService.getCurrentUser();

// Some basic checks; is the ID a valid format, etc. Not relevant,
// but the "response" variable is set if we find a problem

final DeferredResultsResponse deferredResult = new DeferredResultsResponse(runId, runType, userId, returnOnNotDone);
if (response != null) {
deferredResult.setResult(response);
} else {
Thread t = new Thread(() -> completeResult(deferredResult));
t.run();
}

return deferredResult;
}

private void completeResult(final DeferredResultsResponse result) {
final ResultsIdentifier id = new ResultsIdentifier(result.getJobId(), result.getRunType());
int attemptCount = 0;
boolean returnOnUnfinished = result.isReturnOnUnfinished();

while (!result.hasResult() && attemptCount < MAX_ATTEMPTS) {
attemptCount++;
// ------- Problem line: -----------
Optional<JobStatus> statusMaybe = jobStatusService.get(new ResultsIdentifier(result.getJobId(), result.getRunType()));

if (!statusMaybe.isPresent()) {
result.setResult(new ResultsResponse(null, false, null, "Unable to find job status entry."));
continue;
}

JobStatus status = statusMaybe.get();
// Incomplete job cases: sleep or respond "not done" based on the flag
if (!status.isComplete() && returnOnUnfinished) {
result.setResult(new ResultsResponse(false, false, null, null));
continue;
} else if (!status.isComplete()) {
sleep();
continue;
}

// Cases of completion: respond based on success
// Various business logic of processing results
}
if (!result.hasResult()) {
result.setResult(new ResultsResponse(true, false, null, String.format("Time out after %d checks", MAX_ATTEMPTS)));
}
}

问题是这样的:问题行上的查询永远不会报告作业状态的更改。经过一番研究,我找到了 Hibernate 的内部结构。在 SessionImpl 中,有一个 StatefulPersistenceContext 类型的字段,它从第一次从数据库中拉出 JobStatus 对象时就保留了该对象的副本。然后,它在同一 session 中的所有后续查询中重用该副本。

现在,我认为可以通过获取当前 session 并调用clear()或refresh(status)来解决这个问题。然而,对我来说,当其他地方都通过 Spring/JPA 存储库进行中介时,必须拉开 JPA 的帷幕并直接使用 Hibernate 的东西是很糟糕的形式。那么,有什么方法可以标记 ORM XML 文件以排除特定类型在 PersistanceContext 中缓存吗?

<小时/>

作为引用,这里是 JobStatus.xml:

<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
version="2.0">
<entity class="project.model.JobStatus">
<attributes>
<embedded-id name="jobIdentifier" />

<basic name="complete" optional="false" />
<basic name="userId" optional="false" />

<basic name="successful" optional="true" />
<basic name="message" optional="true" />

<basic name="lastUpdateTime" optional="false">
<temporal>TIMESTAMP</temporal>
</basic>
</attributes>
</entity>
</entity-mappings>

jobIdentifier 是一个只包含没有子元素的单个元素的元素。

此外,这是带有事务注释的 JobStatusService:

public interface JobStatusService {

/**
* Retrieve the statuses of all jobs for the current user.
* @return All jobs' statuses
*/
@Transactional(readOnly = true)
Iterable<JobStatus> getAllByUser();

/**
* Retrieve the status of a particular job
* @param identifier the combined job ID and type
* @return The persisted job status
*/
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
Optional<JobStatus> get(ResultsIdentifier identifier);

/**
* Save the passed status, subbing in the current user's ID if none is set,
* and updating the "last updated" time
* @param status the job status object
* @return The persisted status object
*/
@Transactional(readOnly = false)
@Modifying
JobStatus save(JobStatus status);

/**
* Delete the status of a particular job
* @param identifier the combined job ID and type
*/
@Transactional(readOnly = false)
@Modifying
void remove(ResultsIdentifier identifier);

/**
* Remove all stored job statuses for the given user id.
* @param userId User id
*/
@Transactional(readOnly = false)
@Modifying
void clearByUser(String userId);

最佳答案

the ResultsController creates a DeferredResult object and then spins off a thread

事实上,不,它不是这么做的。你永远不会启动线程。您在同一个线程中执行所有操作,并且只有在 completeResult() 返回后才返回延迟结果。要真正启动一个线程,您必须替换

t.run();

t.start();

现在,为了确保问题行始终进入数据库并重新加载作业状态的新值,您应该做的是确保 jobStatusService.get() 在单独交易。使用 Spring,通常通过使用注释方法来完成

@Transactional(propagation = Propagation.REQUIRES_NEW)

关于java - 从 Hibernate persistenceContext 缓存中排除 JPA 实体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29505231/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com