2017-03-16 79 views
1

我最近开始使用SOAP webservices,Spring和Hibernate开发一个项目。处理请求后持久化会话对象的数据

我面临着以下问题:

我们使用SOAP UI发送请求来测试我们的代码。我已经写了一个处理账单的服务。基本上有两项服务,一项是创建账单,另一项是账单处理。

我们有一个表BillTb。在处理账单之前,我们检查账单的状态。如果账单状态为3(待定),我们处理它。如果不等于3,我们不处理它。账单处理完毕后,我们将状态更改为4(已处理)。

现在,如果该法案状态为3,我们做了一些其他表中,最后的条目,状态变更为4

如果在处理之间,如果处理失败,我们需要恢复所有那些条目。所以我们在一个事务中调用这些条目。

DAO层与休眠代码如下:

import javax.persistence.EntityManager; 
    import javax.persistence.PersistenceContext; 
    import javax.persistence.PersistenceContextType; 
    import javax.persistence.Query; 

     @PersistenceContext(type = PersistenceContextType.EXTENDED) 
      private EntityManager entityManager; 

     public class BillDAOImpl implements BillDao { 

     ... 
     ... 
     ... 

     int pendingStatus = 3; 
     int processedStatus = 4; 

     Session session = null; 

     for(int id: ids){ 

      Bill bill = null; 


     try{ 
      session = entityManager.unwrap(Session.class); 

      bill= entityManager.find(Bill.class, id); 

      session.getTransaction().begin(); 

      if(bill.status() != pendingStatus){ 
      System.out.println("The bill is already processed"); 
     continue; 
      } 
     ... 
... 
bill.setStatus(processedStatus); 
entityManager.persist(bill); 

      session.getTransaction().commit(); 

     } catch(Exception e){ 

     } 

     } 




     } 

现在的问题是,一旦纸币状态从3改变为4,如果我通过烧制更新查询再次改变状态,以3在数据库中,它应该再次工作,但不知何故,它只读取状态为4。

如果我关闭服务器,然后再次执行请求,那么它适用于相同的条目。

其他与交易有关的参数设置为:

<property name="hibernate.cache.use_query_cache" value="false" /> 

此外,

<bean id="projectEntityManagerFactory" 
     class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
     p:persistenceXmlLocation="classpath*:META-INF/persistence.xml" 
     p:persistenceUnitName="persistenceUnit" p:loadTimeWeaver-ref="loadTimeWeaver" 
     p:jpaVendorAdapter-ref="jpaVendorAdapter" p:jpaDialect-ref="jpaDialect" 
     p:dataSource-ref="datasourceBean"> 
     <property name="jpaProperties"> 
      <props> 
       <prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.BTMTransactionManagerLookup 
       </prop> 
       <prop key="hibernate.transaction.flush_before_completion">false</prop> 
       ... 
       ...    
       <prop key="hibernate.connection.isolation">3</prop> 
       <prop key="hibernate.connection.release_mode">auto</prop> 
      </props> 
     </property> 
    </bean> 

所以在这里似乎会以某种方式保存该法案的对象,当我直接更新该法案的对象数据库,它存储陈旧的数据。那么在这种情况下应该做些什么。我应该在方法结束时清除会话吗?

+0

,这是否状态改变发生的呢?尝试添加impl –

+0

我已经更新了代码。在事务提交之前状态被更新。 – azaveri7

+0

你为什么要搞乱'Entitymanager'和'Session' ......你在不同的对象上重新开始会话。我强烈建议清理你的代码(使用'EntityManager'并且不要将它解开到'Session'中。 –

回答

0

您应该在事务内部执行查询,并且记得每次提交事务(如果触发continue,那是ommited)。

其实我会写这样的:

for(int id: ids){ 

     Bill bill = null; 

     Transaction tx = session.getTransaction(); 
     tx.begin(); 

     try{   
      bill= entityManager.find(Bill.class, id); 

      if(bill.status() != pendingStatus){ 
      System.out.println("The bill is already processed"); 
      tx.commit(); 
      continue; 
      } 

      bill.setStatus(processedStatus); 
      entityManager.persist(bill); 

      session.flush(); 
      tx.commit(); 
     }catch(Exception e){ 
      tx.rollback(); 
      throw e; 
     } 
    } 
+0

这似乎是有效的。只有最后一个问题,如果我最终放入它,它总是会尝试提交如果发生异常,它会去Catch block并且会有回滚,所以我不能在最后提交..所以任何解决方案。 – azaveri7

+0

yes good spot。试试我的更新版本 –

+0

这里有2个尝试块和一个没有任何finally或catch块,我认为它会给编译错误,我尝试了很多组合,但无法弄清楚在哪里刷新会话。上面的一个不起作用,因为如果有一个账单被成功处理,另一个账单失败,它将会因为事务提交到外面而回滚这两个账单对象。 – azaveri7

相关问题