我正在开发一个基于Spring的服务器。我有两个Controllers
正在侦听不同的http请求。它们都有一个变量引用相同的Repository
和@Autowired
注释。
@Controller
public class ClientController {
@Autowired
NodeRepository nodeRepository;
...
}
@Controller
public class NodeController {
@Autowired
NodeRepository nodeRepository;
...
}
所有数据库操作都是使用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);
}
行为如下:
当ClientController
收到新请求时,会对其进行处理,并且Controller会向外部设备发送请求并等待其回答。
这个答案由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());
以下是打印数据:
BEFORE:
321: dead
1: dead
4: dead
AFTER:
321: dead
4: dead
1: dead
正如您所看到的,状态是相同的,但第二次应该是“活着”。
我检查了数据是否正确存储,确实存储了。在解锁ClientController之前,新数据在数据库中可用。
我还尝试使用JDBC,Repository的intead来检索新数据。在这种情况下,正确检索新信息。所以我认为它必须与Repository
有关,但我无法找到它。也许有一些缓存或刷新问题。我尝试在保存新数据后立即执行nodeRepository.flush()
,并在检索之前立即执行{{1}},但它没有用。
我希望有人可以帮助我。提前致谢
答案 0 :(得分:4)
最后我能找到答案。问题确实与一些缓存问题有关。
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();
答案 1 :(得分:-1)
EntityManager entityManager;
@Autowired
public Service(final EntityManager entityManager) {
this.entityManager = entityManager;
}
entityManager.clear();
这对我有用,谢谢