Michi
Michi

Reputation: 41

How to fix 'no entitymanager with actual transaction' when deleteallby method gets called?

I am building a spring boot back-end and want to make a rest end-point, that deletes all item by the suppliers id. When I call the rest end-point, I get 'no entitymanager with actual transaction available' exception.

How can I fix this error?

I tried the @Transactional annutation, but the error still occurs

Model:

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;
    }  
}

Repository:

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

Controller:

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>

I expect the item to be deleted, but it throws:

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

Upvotes: 2

Views: 21962

Answers (3)

Lor&#225;nd P&#233;ter
Lor&#225;nd P&#233;ter

Reputation: 314

I also faced this issue, but the the @Transactional annotation didn't solve it.

I had a strange problem: I didn't add @SpringBootApplication to my Main class. Adding this annotation solved my problem.

Upvotes: 0

wutzebaer
wutzebaer

Reputation: 14875

To explain why @Transactional is needed:

Whan you look at the CrudMethodMetadataPostProcessor.postProcess method, all Methods contained in the implementations set are called with the TransactionSynchronizationManager. Custum Functions need to add Transactions manually.

Upvotes: 3

Michi
Michi

Reputation: 41

Ok, it was my mistake, because I put the @Transactional at the wrong place. I had to put the annutation on the method in my controller, not in the CrudRepository.

Repository:

public interface ItemRepository extends CrudRepository<Item, Integer> {

    public void deleteAllBySuppid(int suppid);
}

Controller:

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

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

Upvotes: 2

Related Questions