将@Transactional从Repository移到Service后出现ORA-00900无效SQL语句错误
问题根因与修复方案
核心原因
@Modifying是Spring Data JPA专门为Repository层接口方法设计的注解,仅在Repository层生效,放到Service层方法上不会被JPA框架识别。
当Repository层的删改方法没有@Modifying注解时,JPA会默认将该方法对应的SQL当做查询语句处理,调用JDBC的executeQuery()执行,而delete语句本身不属于查询类SQL,执行时就会抛出ORA-00900: Invalid SQL Statement语法错误。@Transactional注解可以放在Service层做全局事务管控,无需强制放在Repository层。
正确调整方案
保留Repository层方法上的@Modifying注解,@Transactional可以放在Service层即可,两者不冲突。
修正后代码
Repository层代码
@Repository("someRepository") public interface SomeRepository extends CrudRepository<SomeEntity, String>{ // @Modifying 必须保留在Repository的修改类方法上 @Modifying @Query(nativeQuery = true, value = "delete from some_table where col = :param") int repoDelete(@Param("param") String param); }
Service层代码
@Service(value = "someService") public class SomeServiceImpl implements SomeService { @Autowired SomeRepository repo; @Override @Transactional public void serviceDelete(String id) throws UdhException { // Service层不需要加@Modifying注解,框架不会识别 repo.repoDelete(id); } }
补充说明
如果需要支持Repository层方法单独调用时也能正常开启事务,可以同时在Repository的方法上添加@Transactional注解,默认的REQUIRED事务传播机制会自动复用Service层开启的事务,不会产生冲突。
内容的提问来源于stack exchange,提问作者medmoufahim
相关产品推荐
相关产品推荐

