简体   繁体   English

具有JPA事务的JAX-WS Web服务

[英]JAX-WS Webservice with JPA transactions

I'm going to become mad with JPA... 我要对JPA感到生气...

I have a JAX-WS Webservice like that 我有一个像这样的JAX-WS Web服务

@WebService
public class MyService
{
    @EJB private MyDbService myDbService;

    ...
    System.out.println(dmrService.read());
    ...
}

My EJB contains 我的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;
}

In my persistence.xml the mypu has transaction-type="JTA" and a jta-data-source 在我的persistence.xmlmypu具有transaction-type="JTA"和一个jta-data-source

If I call the webservice, it's working. 如果我呼叫网络服务,则它正在运行。 The entity is retrieved from the db. 从数据库中检索实体。

Now, using an external tool, I'm changing the value of one field in my record. 现在,使用外部工具,我正在更改记录中一个字段的值。

I'm calling the webservice again and ... the entity displayed contains the old value. 我再次调用Web服务,并且...显示的实体包含旧值。

If I'm deploying again, or if I'm adding a entityManager.refresh(myEntity) after the request, I have the good value again. 如果我要再次部署,或者如果在请求之后添加了entityManager.refresh(myEntity),我将再次具有良好的价值。

In @MyTwoCents answer , Option 2 is to NOT use your 'external' tool for changes, use your application instead. 在@MyTwoCents 答案中 ,选项2是不要使用“外部”工具进行更改,而应使用您的应用程序。 Caching is of more use if your application knows about all the changes going on, or has some way of being informed of them. 如果您的应用程序知道所有正在进行的更改,或者可以通过某种方式获悉它们,则缓存将更有用。 This is the better option, but only if your application can be the single access point for the data. 这是更好的选择,但前提是您的应用程序可以是数据的单个访问点。

Forcing a refresh, via EntityManager.refresh() or through provider specific query hints on specific queries, or by invalidating the cache as described here https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching#How_to_refresh_the_cache is another option. 另一种选择是通过EntityManager.refresh()或通过特定查询的提供者特定查询提示或通过使高速缓存无效来强制刷新,如此处所述https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching#How_to_refresh_the_cache This forces JPA to go past the cache and access the database on the specific query. 这将迫使JPA超过缓存并根据特定查询访问数据库。 Problems with this are you must either know when the cache is stale and needs to be refreshed, or put it on queries that cannot tolerate stale data. 问题是您必须知道缓存何时过期并且需要刷新,或者将其置于不能容忍过期数据的查询上。 If that is fairly frequent or on every query, then your application is going through all the work of maintaining a cache that isn't used. 如果那是相当频繁的情况或针对每个查询,那么您的应用程序将完成维护未使用的缓存的所有工作。

The last option is to turn off the second level cache . 最后一个选项是关闭第二级缓存 This forces queries to always load entities into an EntityManager from the database data, not a second level cache. 这将强制查询始终从数据库数据而不是二级缓存将实体加载到EntityManager中。 You reduce the risk of stale data (but not eliminate it, as the EntityManager is required to have its own first level cache for managed entities, representing a transactional cache), but at the cost of reloading and rebuilding entities, sometimes unnecessarily if they have been read before by other threads. 您可以降低陈旧数据的风险(但不能消除它,因为EntityManager需要拥有自己的托管实体的第一级缓存,代表事务性缓存),但要以重新加载和重建实体为代价,有时,如果它们具有之前已被其他线程读取。

Which is best depends entirely on the application and its expected use cases. 最佳选择完全取决于应用程序及其预期的用例。

Don't be mad its fine 别生气了

Flow goes like this. 流程是这样的。

  • You fired a query saying where type="xyz" 您触发了一个查询,说其中type =“ xyz”
  • Now Hibernate keeps this query or state in cache so that if you fire query again it will return same value if state is not changes. 现在,Hibernate将此查询或状态保留在缓存中,以便再次触发查询时,如果状态未更改,它将返回相同的值。
  • Now you are updating detail from some external resource. 现在,您正在从一些外部资源更新详细信息。
  • Hibernate doesnt have any clue about that Hibernate没有任何线索
  • So when you fire query again it returns from catch 因此,当您再次触发查询时,它会从catch中返回
  • When you do refresh, hibernate gets detail from Database 刷新后,休眠将从数据库中获取详细信息

Solution : 解决方案:

  1. So you can either add refresh before calling get call 因此,您可以在致电get call之前添加刷新

OR 要么

  1. Change the Table value using Hibernate methods in Application so that Hibernate is aware about changes. 使用Application中的Hibernate方法更改Table值,以便Hibernate知道更改。

OR 要么

  1. Disable Hibernate cache to query each time from DB (not recommended as it will slow down stuff) 禁用Hibernate缓存以每次从数据库中查询(不建议这样做,因为它会减慢速度)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM