【发布时间】:2015-03-27 07:02:17
【问题描述】:
当相同的查询在每次调用后返回不同的结果时,我的问题与奇怪的读取/选择行为有关。我的情况描述如下:
我有以下代码,从数据库返回文档列表
@RequestMapping(value={"/docs"}, method = RequestMethod.GET)
@ResponseBody
public ArrayList<Document> getMetaData(ModelMap modelMap) {
return (ArrayList<Document>)documentDAO.getDocuments();
}
DocumentDAO.getDocuments 看起来像
public List<Document> getDocuments() {
Query query = entityManager.createQuery("from Document");
List<Document> list = query.getResultList();
for(Document doc:list) System.out.println(doc.getName()+" "+doc.isSigned());
return list;
}
在其他控制器中,我还提取 Document 并更改布尔属性
Document doc = documentDAO.getDocumentById(id)
doc.setSigned(true);
documentDAO.updateDocument(doc); // IS IT NECESSARY??
getById 和 updateDocument 如下:
public Document getDocumentById(Long id) {
return entityManager.find(Document.class, id);
}
@Transactional
public void updateDocument(Document document) {
entityManager.merge(document);
entityManager.flush();
}
问题:
- 据我所知,设置托管对象的属性足以将更改传播到数据库。但我想立即刷新更改。我的额外调用更新方法是合适的解决方案还是调用setter足以立即更改数据库?通过额外更新我的意思是
documentDAO.updateDocument(doc); // IS IT NECESSARY?? - JPA 如何存储托管对象——在一些内部数据结构中,还是简单地将它们保存在像
Document doc;这样的引用中?内部结构很可能使重复/相同 ID 托管对象成为不可能,引用很可能使具有相同 ID 和其他属性的多个托管对象成为可能。 -
merge如何在内部工作 - 尝试在内部存储中查找具有相同 ID 的托管对象,并在检测到的情况下刷新其字段或仅更新数据库? - 如果内部存储确实存在(很可能这是持久性上下文,进一步说 PC),区分托管对象的标准是什么? @Id 注释 hibernate 模型的字段?
我的主要问题是entityManager.createQuery("from Document"); 的结果不同
System.out.println(doc.getName()+" "+doc.isSigned()); 在奇数调用时显示 isSigned true,在偶数调用时显示 false。
我怀疑第一个 select-all-query 返回带有 isSigned=false 的实体并将它们放到 PC 上,之后用户执行一些操作,通过 ID 获取实体,设置 isSigned=true 并且刚刚提取的实体与 PC 中已经存在的实体冲突。 第一个对象 isSigned=false,第二个对象 isSigned=true,PC 混淆并轮流返回不同的托管对象。 但这怎么可能呢?在我看来,PC 有机制通过为每个唯一 id 只保留一个托管对象来避免这种令人困惑的模棱两可的情况。
【问题讨论】:
标签: java hibernate jpa persistence entitymanager