调用@DeleteMapping接口报错:不允许在共享EntityManager创建事务
嘿,别担心,我来帮你拆解这个问题~
你看到的错误提示:
"Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead"
核心原因很简单:你当前使用的EntityManager是Spring容器管理的共享实例,这种实例不允许手动调用begin()/commit()来操控事务,必须用Spring提供的事务管理机制才行。
你的代码问题出在哪?
在你的deleteData方法里,你手动写了事务的开启和提交逻辑:
em.getTransaction().begin(); em.remove(dataRem); em.getTransaction().commit();
但Spring默认注入的EntityManager是「容器共享」的,它的事务生命周期由Spring管控,不是让开发者手动操作的,所以才会抛出这个错误。
两种简单的修复方案(推荐第一种,适合新手)
方案一:用Spring的@Transactional注解(最省心)
只需要在你的方法上添加@Transactional注解,Spring就会自动帮你处理事务的开启、提交(出错时还会自动回滚),你完全不用再写手动事务的代码:
import org.springframework.transaction.annotation.Transactional; @DeleteMapping("/removedata/{id}") @Transactional // 关键:加上这个注解 public ResponseEntity deleteData(@PathVariable String id) { long remInt = Long.parseLong(id); Data dataRem = em.find(Data.class, remInt); em.remove(dataRem); // 直接执行删除,事务交给Spring管理 return ResponseEntity.ok(new MessageResponse("Data removed")); }
小提示:Spring Boot项目只要引入了
spring-boot-starter-data-jpa依赖,事务配置会自动完成,不用额外操作。
方案二:通过EntityManagerFactory创建本地EntityManager(不推荐新手)
如果你一定要手动控制事务,可以注入EntityManagerFactory,创建一个「本地独占」的EntityManager实例,这种实例支持手动事务操作:
import javax.persistence.EntityManagerFactory; import javax.persistence.EntityManager; import org.springframework.beans.factory.annotation.Autowired; @Autowired private EntityManagerFactory emf; @DeleteMapping("/removedata/{id}") public ResponseEntity deleteData(@PathVariable String id) { long remInt = Long.parseLong(id); EntityManager em = emf.createEntityManager(); // 创建本地实例 em.getTransaction().begin(); Data dataRem = em.find(Data.class, remInt); em.remove(dataRem); em.getTransaction().commit(); em.close(); // 必须手动关闭实例,不然会占用资源 return ResponseEntity.ok(new MessageResponse("Data removed")); }
这种方法需要你自己管理EntityManager的生命周期,容易出现资源泄漏的问题,所以更推荐第一种方案。
给新手的额外建议
如果是刚学Spring,建议直接用Spring Data JPA提供的JpaRepository接口,它已经封装好了所有基础的增删改查操作,连EntityManager都不用你自己写,代码会更简洁可靠~
内容的提问来源于stack exchange,提问作者crunchwrap

