S
S
Sergey_USB2021-09-17 13:53:15
Java
Sergey_USB, 2021-09-17 13:53:15

How does @Transactional work? Or what am I doing wrong?

Good afternoon.
real task - there is an application on the client, it sends data to the server, the server writes them to the database, answers the client or everything is OK, the data is written or ERROR ...
If something happened to the database, it hangs, does not respond for a long time - then the client should send that a write error has occurred.
One of the conditions for a normal response is a fast write to the database.
The client, in principle, does not care what happened to the data, whether they signed up or not. He just writes to his log that OK or ERROR.
Data is constantly flying - the loss of one packet is not terrible.

I wanted to play around with the database freeze and the long response in this bundle.

For testing I did the following:

@Transactional(timeout = 20)
    public void generate() {

        for (int i = 0; i < 200; i++) {
            List<TagEntity> list = new ArrayList<>();
            for (int j = 0; j < 50_000; j++) {
                int random_number = (int) (Math.random() * 10);
                TagEntity tagEntity = new TagEntity();
                tagEntity.setTag("Tag_" + random_number);
                list.add(tagEntity);
            }
            tagRepository.saveAll(list);
        }
    }

This is a service - writes to the tagRepository repository.
This method is called from the controller.
We create a package of 50 thousand TagEntities (only two fields - ID and Tag (string))
and write to the database, and so on 200 times.
In this form, this method crashes on the second or third round with the required error - transaction time exceeded.

But if you change this code - like this:
public void generate() {

        for (int i = 0; i < 200; i++) {
            List<TagEntity> list = new ArrayList<>();
            for (int j = 0; j < 50_000; j++) {
                int random_number = (int) (Math.random() * 10);
                TagEntity tagEntity = new TagEntity();
                tagEntity.setTag("Tag_" + random_number);
                list.add(tagEntity);
            }
            saveList(list);
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 6)
    public void saveList(List<TagEntity> list) {
        tagRepository.saveAll(list);
    }

then it will work until all is fulfilled.
even if the database is suspended for a long time, if you run several instances of the record, in short, what not to do - it does not fall on timeout in any way.
propagation - does not matter, this option remained after the last test.

Question - how to make, with a long response from the database, return an error - and not wait for the transaction to complete?

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question