Robin Jonsson
Robin Jonsson

Reputation: 2851

Spring Data Transaction spanning multiple Repositories

I have the need to insert 2 different entities into 2 different tables, using the same transaction. If the second insert fails, the first one should be rolled back.

Is there any way of doing this nicely?

Pseudo code:

start tx
repo1.save(myEntity);
repo2.save(anotherEntity);
try commit

I know you can leverage @Transactioal but only on method level?

Upvotes: 15

Views: 12233

Answers (3)

xyz
xyz

Reputation: 5407

  1. you need check that you don't have set autocommit = false.

  2. wrap save operations into one service method and make it @Transactional. But if you use save() custom method check that save in not marked as @Transactional with propagation level required_new or nested. If you need you can use REQUIRES_NEW for saving service method to make this service method transaction independent of other transactions.

also you can wrap in with TransactionTemplate.

@Autowired
private TransactionTemplate transactionTemplate;

transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    @Override
    public void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
            repo1.save(myEntity);
            repo2.save(anotherEntity);
    });

Upvotes: 12

Shailesh Pratapwar
Shailesh Pratapwar

Reputation: 4224

Steps to follow:

  1. Ensure you use Interfaces for repo1 and repo2 methods as spring transactions works on proxy. ( If you use only classes, then you may need to add few other dependencies).
  2. Annotate repo1.save(..) and repo2.save(..) with @Transactional(propagation=Propagation.REQUIRED) annotation.
  3. Call repo1.save() from any method outside of class.
  4. Unit test the code properly using special junit runner.

Upvotes: -3

Adrian Shum
Adrian Shum

Reputation: 40036

It is usually a wrong idea to have @Transactional declared around repository methods.

Repositories are only for you to access domain entities. Business logic normally involves multiple domain entities and collaborations between them.

In your architecture you should have a layer to compose business logic. This usually corresponds to a service exposed to external.

This is usually the place you should have your transaction boundary set on. Usually it is a Controller, or a Service method.

Upvotes: 11

Related Questions