【问题标题】:JAX-WS Webservice with JPA transactions带有 JPA 事务的 JAX-WS Web 服务
【发布时间】:2019-03-09 14:44:12
【问题描述】:

我要被 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 中,myputransaction-type="JTA"jta-data-source

如果我调用网络服务,它就会工作。从数据库中检索实体。

现在,我使用外部工具更改记录中一个字段的值。

我再次调用 web 服务,并且...显示的实体包含旧值。

如果我再次部署,或者如果我在请求后添加 entityManager.refresh(myEntity),我将再次获得良好的价值。

【问题讨论】:

    标签: java jpa eclipselink weblogic12c


    【解决方案1】:

    在@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 需要为托管实体拥有自己的一级缓存,代表事务缓存),但代价是重新加载和重建实体,如果它们有,有时是不必要的之前被其他线程读取过。

    哪个最好完全取决于应用程序及其预期的用例。

    【讨论】:

      【解决方案2】:

      别生气没关系

      流程是这样的。

      • 您发起了一个查询,说 where type="xyz"
      • 现在 Hibernate 将此查询或状态保存在缓存中,这样如果您再次触发查询,如果状态未更改,它将返回相同的值。
      • 现在您正在从一些外部资源更新详细信息。
      • Hibernate 对此一无所知
      • 因此,当您再次触发查询时,它会从 catch 返回
      • 刷新时,hibernate 从数据库中获取详细信息

      解决方案:

      1. 因此您可以在调用 get 调用之前添加刷新

      1. 使用应用程序中的 Hibernate 方法更改表值,以便 Hibernate 了解更改。

      1. 禁用 Hibernate 缓存以每次从 DB 查询(不推荐,因为它会减慢速度)

      【讨论】:

      • 感谢 MyTwoCents。所以这是正常行为。 '打电话之前接电话'对你来说是什么意思?添加 entityManager.refresh(myEntity);就在返回 myEntity 之前?你能多开发一点你的解决方案 2 吗? 1 和 2 之间最好的是什么?
      猜你喜欢
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-09
      • 2010-10-16
      • 2014-10-28
      相关资源
      最近更新 更多