rxjava2-jdbc icon indicating copy to clipboard operation
rxjava2-jdbc copied to clipboard

Having a tough time with Tx

Open Mu4h4h4 opened this issue 6 years ago • 4 comments

Hello there!

I feel that I'm over complicating over, possibly overkilling it... but I need the following operations to be within a transaction:

  1. Update parent resource
  2. Delete orphan child resource
  3. Update child resource
  4. Insert new child resource
  5. Fetch just updated parent resource
  6. Fetch all child resources

My code looks like this so far...

        try (Database database = Database.fromBlocking(dataSource)) {
            return database.update(updateParentResourceQuery)
                    .parameter()
                    .transacted()
                    .counts()
                    .flatMap(tx -> {
                        return tx.update(deleteChildResource)
                                .parameter()
                                .counts()
                                .flatMap(tx2 -> {
                                    TransactedUpdateBuilder createChildResource = tx2.update(createChildResourceQuery);
                                    childResourcesToBeCreated.forEach(entityLanguage -> createChildResource
                                            .parameter());
                                    return createChildResource
                                            .counts()
                                            .flatMap(tx3 -> {
                                                TransactedUpdateBuilder updateChildResource = tx3.update(updateChildResourceQuery);
                                                childResourcesToBeUpdated.forEach(
                                                        entityLanguage -> updateChildResource
                                                                .parameter());
                                                return updateChildResource
                                                        .counts()
                                                        .flatMap(tx4 -> {
                                                            return tx4.select(selectParentResource)
                                                                    .parameter()
                                                                    .transactedValuesOnly()
                                                                    .get(new Mapper())
                                                                    .flatMap(tx5 -> {
                                                                        return tx5
                                                                                .select(selectAllChildResources)
                                                                                .parameter()
                                                                                .valuesOnly()
                                                                                .get(new Mapper())
                                                                                .flatMap(childResources -> {
                                                                                    ParentResource parentResource = tx5.value();
                                                                                    parentResource.setChildResources(childResources);
                                                                                    return Flowable.just(parentResource);
                                                                                });
                                                                    });
                                                        });
                                            });
                                });
                    });
        }

It doesn't work. When I do the parent update and fetch it back it works, but when I start chaining the operations everything goes haywire.

Any input will be much much appreciated!

Thank you very much for your time!

Mu4h4h4 avatar Apr 04 '18 03:04 Mu4h4h4

Yep that's ugly isn't it. We need some other patterns. I sometimes just block to get simpler code, that is an option. Once you have the first tx you can use that across a sequence of blocking calls if it's easier.

In terms of it working or not, I'd like to have a repeatable unit test, preferrably using Database.test() like in the README.md. If you can knock one up, great!

davidmoten avatar Apr 04 '18 04:04 davidmoten

When is the transaction commit/rollback? (since I could span the initial tx across multiple methods for each operation) I will try to put up the test cases in a bit, for now I'm in a bit of a time crunch I'm giving the raw jdbc a go.

Mu4h4h4 avatar Apr 04 '18 04:04 Mu4h4h4

So throughout there is only one actual transaction of course and that is presented to you in that first tx. When that outer Flowable terminates then the transaction will be committed or rolled back as appropriate.

davidmoten avatar Apr 04 '18 05:04 davidmoten

In terms of patterns I just remembered that in rxjava-jdbc we offered a dependsOn method. See https://github.com/davidmoten/rxjava-jdbc#dependencies. Once you've got a tx you start using it with dependsOn and no blocking required. Don't think rxjava2-jdbc has it but we can add it.

davidmoten avatar Apr 05 '18 03:04 davidmoten