Spring boot 在采用过时值的事务中执行的Spring本机查询

Spring boot 在采用过时值的事务中执行的Spring本机查询,spring-boot,transactions,spring-data,spring-data-jpa,Spring Boot,Transactions,Spring Data,Spring Data Jpa,我正在使用SpringBoot(1.4.4.REALEASE)和Spring数据来管理MySql数据库。我有以下情况: 我们使用修订服务更新在一台设备中执行的一次修订 修订服务保存修订并调用设备服务更新设备状态 updateEquipmentStatus调用Db存储过程,以评估设备及其修订版并更新字段 我尝试了一些选项,但没有获得设备的更新状态。updateeEquipmentStatus方法保持写入设备的以前状态(不考虑事务中存储的当前版本)。代码是这样编写的: 修订服务 @服务 公共类修正服

我正在使用SpringBoot(1.4.4.REALEASE)和Spring数据来管理MySql数据库。我有以下情况:

  • 我们使用
    修订服务
    更新在一台设备中执行的一次修订
  • 修订服务
    保存修订并调用
    设备服务
    更新设备状态
  • updateEquipmentStatus调用Db存储过程,以评估设备及其修订版并更新字段
  • 我尝试了一些选项,但没有获得设备的更新状态。
    updateeEquipmentStatus
    方法保持写入设备的以前状态(不考虑事务中存储的当前版本)。代码是这样编写的:

    修订服务

    @服务
    公共类修正服务{
    @org.springframework.transaction.annotation.Transactional
    公共长期保存修订版(修订版){
    //使用JPA Hibernate保存修订
    回购保存(修订版);
    设备服务。更新设备状态(IDEEquipment);
    }
    }
    
    设备服务

    @服务
    公共类设备服务{
    @org.springframework.transaction.annotation.Transactional
    公共长更新设备状态(长IDEEquipment){
    回购更新设备状态(IDEEquipment);
    }
    }
    
    设备回购

    @存储库
    公共接口设备REPO扩展CrudRepository{
    @修改
    @程序(name=“pupdate\u设备\u状态”)
    void updateeEquipmentStatus(@Param(“id_Param”)Long idEquipment);
    }
    
    据我所知,由于这两个方法都是用Spring的transactional注释的,因此
    updateeEquipmentStatus
    方法应该在当前事务的范围内执行。我还尝试了来自
    updateeEquipmentStatus
    @Transactional
    注释的不同选项,例如
    @Transactional(隔离=隔离.读取未提交)
    (这不应该是必需的,因为我使用的是相同的事务)和
    @Transactional(传播=传播.需要新)
    ,但一直没有考虑到目前的状况。我的存储过程就是这样保存到MySql数据库中的:

    CREATE DEFINER=`root`@`localhost`PROCEDURE`pupdate\u device\u status`(在`id\u param`INT中)
    语言SQL
    不确定
    修改SQL数据
    SQL安全定义程序
    注释“”
    开始
    /*根据精装配件和trevision*执行更新
    /*要计算设备状态,此处不管理任何事务*/
    结束
    
    我还想澄清,如果我对设备本身进行了一些修改(仅影响tequipment),则状态将得到适当更新。InnoDb是用于所有表的引擎


    更新

    刚刚将repo方法改为使用nativeQuery,同样的问题不断发生,因此应该放弃所涉及的Db过程:

    修改 @查询(nativeQuery=true,value=“更新tequipment set equipment_status=(情况为(…)”) void updateeEquipmentStatus(@Param(“id_Param”)Long idEquipment);
    更新2

    做了更多的测试并在方法中添加了日志,这就是具体的问题:

    • 更新功能会正确选择设备服务中所做的更改(当tequipment中的某些内容发生更改时,tequipment中的状态会正确计算)
    • 在修订服务(trevision)中所做的更改会导致精装配件中的值过时(Spring是否在其他事务中使用REQUIRES_NEW进行更改并不重要)。Spring在使用REQUIRES_new in
      establishEquipmentStatus
      时似乎正确地创建了一个新事务,因为当前事务名称已更改,但本机查询没有最新的值(因为未提交之前的事务?)。还尝试从
      establishEquipmentStatus
      中删除
      @Transactional
      ,以便使用相同的事务,但问题不断发生
    • 我想突出显示用于更新设备状态的查询具有使用trevision的多个子查询

    更改为read uncommitted是正确的想法,但在调用存储过程之前,还需要刷新entitymanager。请参阅此线程:


    就我个人而言,我会在Spring中完成这一切,除非您完全被迫使用存储过程。

    添加以下代码可以修复它(以编程方式将事务状态刷新到数据库):

    @服务
    公共类设备服务{
    @持久上下文
    私人实体管理者实体管理者;
    @org.springframework.transaction.annotation.Transactional
    公共长更新设备状态(长IDEEquipment){
    entityManager.flush();
    回购更新设备状态(IDEEquipment);
    }
    }
    

    不过,如果能找到一种声明式的方式来做这件事,那就太好了。

    嗨,很抱歉耽搁了。实际上,问题不是特定于存储过程的,但似乎更多地与同一事务中涉及的多个表有关(它使用旧表值)。或多或少,这就是执行流程:1。使用Hibernate更新修订版。2.执行
    updateeEquipmentStatus
    方法,该方法触发一个修改本机查询(此查询使用步骤1中涉及的一些过时数据)。