2017년 10월 10일 화요일

Spring transaction propagation test [REQUIRES_NEW]

We will test the propagation of spring transaction.

First of all, you can declare [PersonService] that use the table named person.
That service will be using PersonNewService that can be changed the propagation of transaction by the user.
And then you can check the commit, rollback states.

@Service
@Transactional
@Slf4j
public class PersonServiceImpl implements PersonService {

    @Autowired
    private PersonRepository personRepository;

    @Autowired
    private PersonNewService personNewService;

    @Override
    @Transactional
    public void addPerson(String name) throws Exception {
        Person person = new Person();
        person.setName(name);
        personRepository.save(person);

        personNewService.addNewPerson("newName");
        
    }
}

@Service
@Slf4j
public class PersonNewServiceImpl implements PersonNewService {

    @Autowired
    private PersonRepository personRepository;

    @Autowired
    private PersonService personService;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addNewPerson(String newName) {

        Person newPerson = new Person();
        newPerson.setName(newName);
    }
}

I'm going to check the logic whether it's working fine.

When the API is called, you can see the result as below.

mysql> select * from person;
+----+---------+
| id | name    |
+----+---------+
| 18 | dfefe   |
| 19 | newName |
+----+---------+
2 rows in set (0.00 sec)


By using "TransactionSynchronizationManager.getCurrentTransactionName()",
you can check that these two methods are working in different transaction each.

2017-10-08 18:06:41.383  INFO 15092 --- [nio-8080-exec-1] o.b.t.p.service.impl.PersonServiceImpl   : addPerson : org.blog.test.person.service.impl.PersonServiceImpl.addPerson
2017-10-08 18:06:41.388  INFO 15092 --- [nio-8080-exec-1] o.b.t.p.s.impl.PersonNewServiceImpl      : addNewPerson : org.blog.test.person.service.impl.PersonNewServiceImpl.addNewPerson

When exception occured, I will check the rollback and commit state.
Exception occured by the method 'throw new RuntimeException();'.

1. After addNewPerson is called, In addPerson,Exception occured

기존의 transaction A가 실행되고, 새로운 transaction B가 실행되고 commit된 이후,
transaction A로 다시 돌아와서 해당 transaction A가 끝나기 전 Exception이 발생한 경우입니다.

transaction A was executed, and then new transaction B is executed and committed.
After that, exception occured before transaction A ended.

In API, exception occured, however, transaction B is already committed.
So the statement in transaction B is inserted regardless of exception.
However, rollback occured in transaction A, so the statement in transaction A is not inserted to DB.

mysql> select * from person;
+----+---------+
| id | name    |
+----+---------+
| 23 | newName |
+----+---------+
1 row in set (0.00 sec)


2. Before addNewPerson is called, In addPerson, Exception occured

Before transaction B, rollback occured in transaction A,
So there's no commit in transaction A,B both.

mysql> select * from person;
Empty set (0.00 sec)

3. After addNewPerson is called, in addNewPerson, exception occured

Exception occured in transaction B, and then rollback occured in transaction B.
Transaction A also not committed.

mysql> select * from person;
Empty set (0.00 sec)

4. After addNewPerson is called, exception occured in the method that is called from addNewPerson

External method is also proceed in transaction B. so all the transactions are rollbacked.

mysql> select * from person;
Empty set (0.00 sec)


댓글 없음 :

댓글 쓰기