代码之家  ›  专栏  ›  技术社区  ›  tweetysat

带有JPA事务的JAX-WS-Webservice

  •  0
  • tweetysat  · 技术社区  · 7 年前

    我有一个这样的JAX-WS网络服务

    @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

    如果我打电话给网络服务,它就工作了。从数据库检索实体。

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

    我再打一次网络服务。。。显示的实体包含旧值。

    2 回复  |  直到 7 年前
        1
  •  1
  •   Chris    7 年前

    以我的两美分计 answer

    通过EntityManager.refresh()或通过 provider specific query hints 在特定的查询中,或者通过如下所述使缓存无效 https://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching#How_to_refresh_the_cache

    最后一个选择是 turn off the second level cache . 这迫使查询总是从数据库数据而不是二级缓存将实体加载到EntityManager中。您可以降低过时数据的风险(但不能消除它,因为EntityManager需要为托管实体拥有自己的一级缓存,表示事务性缓存),但代价是重新加载和重建实体,如果其他线程以前读取过实体,则有时是不必要的。

    哪种方法最好完全取决于应用程序及其预期用例。

        2
  •  0
  •   MyTwoCents    7 年前

    别生气,没事

    • 您启动了一个查询,其中type=“xyz”
    • 现在Hibernate将这个查询或状态保存在缓存中,这样,如果您再次启动查询,如果状态没有改变,它将返回相同的值。
    • Hibernate对此一无所知
    • 所以当您再次启动查询时,它会从catch返回
    • 当您刷新时,hibernate从数据库中获取详细信息

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

    或者

    1. 禁用Hibernate缓存,以便每次从DB进行查询(不建议这样做,因为这样会降低速度)