我会对 JPA 感到生气...
我有一个像这样的 JAX-WS Web 服务
@WebService
public class MyService
{
@EJB private MyDbService myDbService;
...
System.out.println(dmrService.read());
...
}
我的 EJB 包含
@Stateless
public class MyDbService
{
@PersistenceContext(unitName="mypu")
private EntityManager entityManager;
public MyEntity read()
{
MyEntity myEntity;
String queryString = "SELECT ... WHERE e.name = :type";
TypedQuery<MyEntity> query = entityManager.createQuery(queryString,MyEntity.class);
query.setParameter("type","xyz");
try
{
myEntity= query.getSingleResult();
}
catch (Exception e)
{
myEntity= null;
}
return myEntity;
}
在我的 persistence.xml
中,mypu
有 transaction-type="JTA"
和 jta-data-source
如果我调用网络服务,它就可以工作。该实体是从数据库中检索的。
现在,我使用外部工具更改记录中一个字段的值。
我再次调用 Web 服务,并且...显示的实体包含旧值。
如果我再次部署,或者在请求后添加一个entityManager.refresh(myEntity),我将再次获得良好的值(value)。
最佳答案
在 @MyTwoCents answer 中,选项 2 是不使用“外部”工具进行更改,而是使用您的应用程序。如果您的应用程序了解所有正在发生的更改,或者有某种方式获知这些更改,那么缓存会更有用。这是更好的选择,但前提是您的应用程序可以成为数据的单一访问点。
通过 EntityManager.refresh() 或特定查询上的 provider specific query hints 强制刷新,或者通过使缓存失效(如此处所述)https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching#How_to_refresh_the_cache 是另一种选择。这会强制 JPA 通过缓存并根据特定查询访问数据库。这样做的问题是,您必须知道缓存何时过时并需要刷新,或者将其放在不能容忍过时数据的查询上。如果这种情况相当频繁或在每个查询上发生,那么您的应用程序将完成维护未使用的缓存的所有工作。
最后一个选项是 turn off the second level cache 。这会强制查询始终从数据库数据(而不是二级缓存)将实体加载到 EntityManager 中。您可以降低过时数据的风险(但不能消除它,因为 EntityManager 需要为托管实体拥有自己的一级缓存,代表事务缓存),但代价是重新加载和重建实体,如果它们有的话,有时是不必要的之前已被其他线程读取过。
哪个最好完全取决于应用程序及其预期用例。
关于java - 具有 JPA 事务的 JAX-WS Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52642793/