Rakesh Singh Balhara
Rakesh Singh Balhara

Reputation: 410

How can I use @Transactional in multithreaded environment

I am doing a insert operation using multi threading. I used the annotated my method is@Transaction annotation. But I am not able to do the insert operation getting below exception.

Exception in thread "Thread-21" javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)

Upvotes: 2

Views: 1175

Answers (2)

Grim
Grim

Reputation: 1974

Because spring beans are wrapped you have to call the wrapped method from a Thread:

@Autowire
private final MyService ms=null;

public void removeMultithreaded(int[] userIds){
  for(int i =0; i< userIds.length; i++) {
    int userId=userIds[i];
    new Thread(()-> ms.delete(userId)).start();
  }
}

In this code you call delete what must be annotated by a @Transactional.

Be warned: The amount of userIds you can delete at the same time is limited by the size of the Connection Pool! Since the delete operation might be faster than the gathering and releasing from a connection pool you might never come into trouble, even if you have to remove a higher amount of users than the Connection Pool allowes.

Upvotes: 1

Antoniossss
Antoniossss

Reputation: 32507

Since there is no code... In order to get it to work you must

  1. Annotate your delete method with @Transactional - lets call it delete
  2. Invocation of that method must be from outside of the bean in order for AOP to kick in

So internal invocations like

void doSomething(){
    this.delete();
}

will not work

but

@Autowired
YourBean bean;

...
bean.delete(); 

will do the job

Upvotes: 4

Related Questions