不能回滚Spring事务

后端开发 2026-07-08

在一个项目中,我需要将一个CSV文件导入数据库,在出现任何问题时这次操作必须回滚。

一个服务调用一个辅助工具,从文件中读取数据并把它们放入一个 List 中,然后它调用一个继承自 CrudRepository 的仓储,以 saveAll() 的方式持久化数据。我在仓储的 saveAll() 上方以及服务的导入方法上添加了 @Transactional 注解。

我的问题是,当运行我的代码时(导入一个缺少字段的CSV文件),会抛出一个 ConstraintViolationException 异常,但回滚并没有执行,数据库中已经持久化的数据仍然留存。

我读到回滚只对未检查异常起作用,所以我把代码中的任何 try/catchthrow 移除了,但问题仍然存在。

我也尝试使用 rollbackFor 属性,但没有效果。

作为Spring的新手,我可能会有些错误,但我想不出到底哪里错了。你能帮我定位问题吗?

先行致谢,以下是我的代码:

ReferentielRIService.java

package com.orange.fafsi.api.referentielRi.service;

import com.orange.fafsi.api.referentielRi.helper.ReferentielRiCsvHelper;
import com.orange.fafsi.api.referentielRi.model.ReferentielRi;
import com.orange.fafsi.api.referentielRi.repository.ReferentielRiRepository;
import com.orange.fafsi.api.state_machine.Cursor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.util.List;
import java.util.logging.Logger;

@Service
public class ReferentielRiService {

    private static final Logger logger = Logger.getLogger("import_ref_ri");

    @Autowired
    private ReferentielRiRepository repository;

    @Autowired
    private ReferentielRiCsvHelper csvHelper;

    @Autowired
    private Cursor cursor;

    @Transactional()
    public void importAll(File file) {

        this.cursor.next();
        List<ReferentielRi> list = this.csvHelper.csvToList(file, false, ',');
        this.repository.saveAll(list);
    }
}

ReferentielRIRepository.java

package com.orange.fafsi.api.referentielRi.repository;

import com.orange.fafsi.api.referentielRi.model.ReferentielRi;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

@Repository
@Transactional()
public interface ReferentielRiRepository extends CrudRepository<ReferentielRi, Long> {

    @Transactional()
    @Override
    <S extends ReferentielRi> Iterable<S> saveAll(Iterable<S> entities);
}

解决方案

你的问题不是你的代码,而是你的表类型。MyISAM表不支持事务,每条语句执行时都像一个独立的自动提交事务。

如果你想要完全可控的事务,需要把表改为INNODB类型。

下面是来自MySQL文档的一个有用链接:17.6.1.5将 MyISAM表转换为InnoDB

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章