Raf*_*ado 2 java spring jpa spring-data-jpa
我正在开发一个基于 Spring 的服务器。我有两个Controllers正在侦听不同的 http 请求。它们都有一个引用Repository与@Autowired注释相同的变量。
@Controller
public class ClientController {
@Autowired
NodeRepository nodeRepository;
...
}
@Controller
public class NodeController {
@Autowired
NodeRepository nodeRepository;
...
}
Run Code Online (Sandbox Code Playgroud)
所有的数据库操作都是通过使用NodeRepository:
public interface NodeRepository extends JpaRepository<Node, Long>{
Node findByNodeId(long nodeId);
List<Node> findByStatusIn(Set<String> status);
List<Node> findByNodeIdIn(Set<Long> ids);
Node findByPhoneNumber(String phoneNumber);
Node findByCloudId(String cloudId);
Node findByDeviceDescription(String deviceDescription);
}
Run Code Online (Sandbox Code Playgroud)
行为如下:
当ClientController接收到一个新的请求时,它被处理并且控制器向外部设备发送一个请求并等待它的答复。
这个答案是由NodeController. 因此,当答案到达时,接收到的信息将保存在数据库中,并向 发送信号ClientController以唤醒它。
当这个控制器被唤醒并试图从数据库中检索更新的信息时,我的问题就出现了。该信息不是刚刚存储的信息,而是之前存储的信息。
这是ClientController块和检索信息发生的代码片段:
// Retrieves the list of nodes that are going to be requested
requestedNodes = (List<Node>) nodeRepository.findAll();
System.out.println("BEFORE");
for (Node node : nodes)
System.out.println(node.getNodeId() + ": " + node.getStatus());
// Sends a request to the nodes
// The Controller is blocked here until all answers have been received
fetchNodes(requestedNodes, DevicePing[0], null);
// Retrieves the list of nodes again
nodes = nodeRepository.findAll();
System.out.println("AFTER");
for (Node node : nodes)
System.out.println(node.getNodeId() + ": " + node.getStatus());
Run Code Online (Sandbox Code Playgroud)
这是打印的数据:
BEFORE:
321: dead
1: dead
4: dead
AFTER:
321: dead
4: dead
1: dead
Run Code Online (Sandbox Code Playgroud)
如您所见,状态是相同的,但第二次它应该是“活着”。
我已经检查过它是否正确存储了数据,确实如此。在解锁 ClientController 之前,新数据在数据库中可用。
我还尝试使用 JDBC 检索新数据,而不是存储库。在这种情况下,新信息被正确检索。所以我认为它一定与 the 相关,Repository但我找不到它是什么。也许有一些缓存或刷新问题。我试图nodeRepository.flush()在保存新数据之后和检索它之前立即执行,但它没有用。
我希望有人可以帮助我。提前致谢
终于我能找到答案了。该问题确实与一些缓存问题有关。
Hibernate 正在缓存使用函数检索到的实体nodeRepository.findAll(),因此当我调用该函数时,nodeRepository.findAll()它会返回缓存的信息,而不是对数据库执行查询。
解决方案是在检索更新的数据之前clear()从EntityManager右侧调用该函数:
// Sends a request to the nodes
// The Controller is blocked here until all answers have been received
fetchNodes(requestedNodes, DevicePing[0], null);
// Clears the cache to avoid inconsistency
entityManager.clear();
// Retrieves the list of nodes again
nodes = nodeRepository.findAll();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5068 次 |
| 最近记录: |