springboot3.0jpa事务出现数据消失问题

背景:我有一个表有三个主键,实体类用@EmbeddedId来设置复合主键,现在就是有一个功能解析文件后插入数据库。有两个文件,两个文件内容完全一样。 然后循环之中,用一个事务platformTransactionManager去控制一个文件,即文件扫描完成后需要删除该主键下的数据,然后再插入数据,如果有一个地方出错就用事务手动回滚,这样就不影响下一个文件扫描。现在就是有一个情况,两个文件内容完全一样,扫描解析文件之后,会先删除相同主键下的数据,然后再插入文件内容数据。而上面说的执行完后,数据库为空,如果我debug第一个文件的comitt之后,是可以看到插入的数据的,而后执行完全一样的文件之后,就消失了。

实体类代码

@Data
@Entity
@Table(name = "report_ar")
public class ReportArRec {
    @EmbeddedId
    private ReportArId id;

    @Column(name = "ric")
    private String ric;
@Data
@Embeddable
public class ReportArId implements Serializable {
    @Column(name = "serial_number")
    private Integer serialNumber;

    @Column(name = "stock_code")
    private String stockCode;

    @Column(name = "report_year")
    private Integer reportYear;

    @Column(name = "report_quarter")
    private String reportQuarter;

下面是我的一个简化业务逻辑代码

        for (MultipartFile file : files) {
         
            if (!file.isEmpty()) {
                TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);
try{
                           deleteArResult = reportArRepository.deleteByCodeAndYearAndQuarter(reportBaseForm.getStockCode(), reportBaseForm.getReportYear(), reportBaseForm.getReportQuarter());
            updateArResult = reportArRepository.saveAll(reportArRecs);
                    platformTransactionManager.commit(transactionStatus);
                } catch (Exception e) {
       
                    platformTransactionManager.rollback(transactionStatus);
                }
            } else {

            }
            
      
        }

下面是我的dao方法库:

@Repository
public interface ReportArRepository extends JpaRepository<ReportArRec, ReportArId>, JpaSpecificationExecutor<ReportArRec> {
    @Transactional
    @Modifying
    @Query("DELETE FROM ReportArRec r WHERE r.id.stockCode = :stockCode AND r.id.reportYear = :reportYear AND r.id.reportQuarter = :reportQuarter")
    int deleteByCodeAndYearAndQuarter(@Param("stockCode") String stockCode, @Param("reportYear") Integer reportYear, @Param("reportQuarter") String reportQuarter);

    @Transactional
    int deleteByIdStockCodeAndIdReportYearAndIdReportQuarter(String stockCode, Integer reportYear, String reportQuarter);

}

总结:当我把删除的方法写成deleteByCodeAndYearAndQuarter这种@Query sql的方式删除时,会出现数据消失的问题,比如,第一个文件commit之后我能在数据库看到数据,继续执行下去,delete之前可以看到数据库有数据,delete之后数据库没有数据了,说明delete是生效的了,但是!saveall之后再打印findall还是空数据,有可能是saveall以为数据库还有数据就不操作了,但是有相同的话应该是更新才对。反正就是deleteByCodeAndYearAndQuarter这种删除有点像假删除,迷惑了saveall这边的操作。而当我尝试性使用jpa方法名查询的方式时,比如deleteByIdStockCodeAndIdReportYearAndIdReportQuarter,前面的问题都解决。虽然都解决了,但我很想知道该怎么排查深层的问题,有点不明所以,所以想问问有没有大佬知道上面这两个删除的区别。这个问题是真滴奇怪,还好有人用了方法名查询这种方法,不然我都不会怀疑到这个删除身上

JPA有缓存对象这个概念,使用entityManager 对象的find方法(查询一条数据)时,首先会在entityManager对象中去查询是否存在一级缓存对象
如果存在:则直接使用,而不会发送SQL语句
所以你可以先FLUSH一下再观察看看

1 个赞