2011-11-27 90 views
3

使用JPA/Eclipse TopLink。使用JPQL createQuery返回的旧数据

我更新(使用createNativeQuery)的表如下所示:

Query query = em.createNativeQuery("UPDATE Products SET productName='" + p.getProductName() + "',productVendor='" + p.getProductVendor() + "',productDescription='" + p.getProductDescription() + "',quantityInStock=" + p.getQuantityInStock() + ",buyPrice =" + p.getBuyPrice() + ",msrp=" + p.getMsrp() + " WHERE productCode='" + p.getProductCode() + "'"); 
query.executeUpdate(); 

更新反映在DB(MySQL的)

对于如下显示检索(使用的createQuery):

Query query1 = em.createQuery("SELECT p from Products p where p.productCode='"+searchTerm+"'"); 
return query1.getResultList(); 

但是,返回的ResultList始终是更新前的数据。但是,当我使用createNativeQuery而不是createQuery时,返回最新的更新数据。 createQuery方法可能会出现什么错误?

回答

6

当您使用批量更新或原生查询时,您绕过了第一级缓存。 Toplink无法知道它已经在第一级缓存中拥有的实体已经发生了变化。因此,必须清除实体管理器才能使查询重新刷新刷新的对象。

但最好的方法可能是首先避免批量更新。您的第一个查询可以由JPQL查询替换,该查询用指定的代码加载产品,然后简单地更新Product实体。即使您保留更新查询,也可以使用JPQL而不是SQL编写(但您仍然遇到问题)。

最后,您的查询应该使用的参数,以避免注射,并确保一切正确转义:

Query query1 = em.createQuery("SELECT p from Products p where p.productCode = :searchTerm); 
query1.setParameter("searchTerm", searchTerm); 
return query1.getResultList(); 
+1

感谢,JB Nizet。这是一个很好的解释。 使用em.clear()清除entitymanager缓存没有帮助。所以我最终绕过了缓存 - query.setHint(“javax.persistence.cache.storeMode”,“BYPASS”);它的工作。 (我明白绕过缓存的全部目的,正如你在文章中提到的那样,将避免使用批量更新和原生查询)。再次感谢。 – srock