【问题标题】:How to fix 'no entitymanager with actual transaction' when deleteallby method gets called?调用 deleteallby 方法时如何修复“没有实体管理器与实际事务”?
【发布时间】:2019-05-20 11:31:14
【问题描述】:

我正在构建一个 Spring Boot 后端,并希望创建一个休息端点,该端点会按供应商 ID 删除所有项目。当我调用其余端点时,我得到“没有实际事务可用的实体管理器”异常。

我该如何解决这个错误?

我尝试了@Transactional注解,但仍然出现错误

型号:

public class Item {

    public Item() {}

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ItemId")
    private int id;
    public int getId() {
        return this.id;
    }
    public void setId(int Id) {
        this.id = Id;
    }

    @Column(name = "Suppid")
    private int suppid;
    public int getSuppid() {
        return this.suppid;
    }
    public void setSuppid(int Suppid) {
        this.suppid = Suppid;
    }  
}

存储库:

public interface ItemRepository extends CrudRepository<Item, Integer> {
    @Transactional
    public void deleteAllBySuppid(int suppid);
}

控制器:

public void deleteSupplier(@RequestParam(name = "suppid") int suppid) {

    itemrepo.deleteAllBySuppid(suppid);
    supprepo.delete(supprepo.findByid(suppid));
}

pom.xml

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.0</version>
    </dependency>

    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.4.0.Final</version>
    </dependency>
</dependencies>

我希望该项目被删除,但它抛出:

Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'remove' call] with root cause

【问题讨论】:

  • 将该逻辑放入服务方法中,并使用@Transactional 注释该方法。那是业务逻辑,属于服务层而不是 Web 层。
  • 你有没有配置过EntityManager
  • 正如@M.Deinum 所说,您必须将逻辑放入服务类中,并使用 {@transactional} 进行注释
  • @M.Deinum,我很抱歉没有尽快回复您的评论,但感谢您为我提供解决方案的提示。我将注释放置在方法上。我知道,我没有一项服务或多项服务,但这个后端是我学校项目的一部分。我是一个使用 Spring Boot 制作后端程序的初学者,我还没有时间阅读服务,因为我希望它能让代码保持简单。但是对于自我教育,我正在听取您的建议,以便将来将所有业务逻辑放入服务中。非常感谢您的帮助。
  • 你真的应该有一个服务层/门面。您不希望您的网络层成为事务边界。

标签: hibernate spring-boot jpa


【解决方案1】:

好吧,这是我的错误,因为我把@Transactional 放错了地方。我必须在我的控制器中的方法上加上注解,而不是在 CrudRepository 中。

存储库:

public interface ItemRepository extends CrudRepository<Item, Integer> {

    public void deleteAllBySuppid(int suppid);
}

控制器:

@Transactional
public void deleteSupplier(@RequestParam(name = "suppid") int suppid) {

    itemrepo.deleteAllBySuppid(suppid);
    supprepo.delete(supprepo.findByid(suppid));
}

【讨论】:

  • 创建一个服务并添加它会更好
【解决方案2】:

解释为什么需要@Transactional

当您查看CrudMethodMetadataPostProcessor.postProcess 方法时,implementations 集中包含的所有方法都使用TransactionSynchronizationManager 调用。自定义函数需要手动添加事务。

【讨论】:

    【解决方案3】:

    我也遇到过这个问题,但是@Transactional 注释没有解决。

    我遇到了一个奇怪的问题:我没有将 @SpringBootApplication 添加到我的 Main 类中。添加此注释解决了我的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-05
      • 2015-02-18
      • 2021-08-10
      • 1970-01-01
      • 2015-01-18
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      相关资源
      最近更新 更多