Hello Lukas,

thanks for following up.

exactly like you said, i wrote the own utility because i want to pass the 
following data from the Manager/Services-Layer into the DAO-Layer for each 
"daoFactory.createXyzDao()" call:
- tenantId
- langId of the user
- the dsl of jooq

when i use the DSLContext.transaction() API directly, the could be not as 
slim, i think. See:

```java

DSLContext ctx = DslContextFactory.createDSLContext(request);

ctx.transaction(trx -> {
    
    AuthorDao authorDao = daoFactory.createAuthorDao(requestContext, trx)

    trx.dsl().transaction(trx1 -> {
        // ..
            BookDao bookDao = daoFactory.createBookDao(requestContext, trx1)
    });

```

the instantiation of the DSLContext necessarily needs to be given the 
"request" object which contains the "tenantId" and the "langId", 
so it can construct the DSLContext by attaching a custom 
"DefaultExecuteListenerProvider" to the configuration of the DSLContext,
so all Queries executed by jooq will be appended a "WHERE tenantId = xyz", 
to automatically make sure that a user of tenant=xyz never
sees or accesses data from an other tenant.

The DAOs must be instantiated with the transaction and data from the 
request context, that can help the abstraction of the DAOs to make stuff,
like using the "langId" of the user, to make sure all queries that select 
something on "Lang" tables than contain a column "langId" to always get the
language-entry of the users "langId" as default-language.

But yes, you are right, it would also be totally fine to directly use the 
jooqs transaction api, but then the developers need to pass more variables 
to 
the constructors of the dao and type a bit more... 


lukas...@gmail.com schrieb am Montag, 25. März 2024 um 07:40:21 UTC:

> Hi Bernd,
>
> The try-with-resources approach will not work unless you're OK with the 
> explicit commit. I've explored this as well in the past:
> https://stackoverflow.com/q/21353508/521799
>
> But you don't really need any of that, as jOOQ's DSLContext.transaction() 
> API already supports this nesting style using lambda expressions, rather 
> than try-with-resources. I take that you wrote your own utility because you 
> need to attach additional semantics with each transaction?
>
> Best Regards,
> Lukas
>
> On Sun, Mar 24, 2024 at 5:23 PM 'Bernd Huber' via jOOQ User Group <
> jooq...@googlegroups.com> wrote:
>
>> i found a solution,
>>
>> i just wrap jooqs `ctx.transaction` lambda-exception
>>
>> the code looks ok that way i guess.
>>
>> ```
>> ...
>> jooqContextFactory.withinTransaction(requestContext, jooqContext -> {
>>   // transaction1
>>
>>   jooqContextFactory.withinTransaction(requestContext, subContextA -> {
>>     // transaction2
>>     ProductRecordDAO aProductRecordDAO = daoFactory
>> .createProductRecordDAO(subContextA);
>>     aProductRecordDAO.deleteDTOs(queryResult);
>>   });
>>
>>   try {
>>     jooqContextFactory.withinTransaction(requestContext, subContextB -> {
>>       // transaction3
>>       ProductRecordDAO bProductRecordDAO = daoFactory
>> .createProductRecordDAO(subContextB);
>>       bProductRecordDAO.insertDTOs(inserts);
>>       // Integer x = Integer.valueOf("test");
>>     });
>>   } catch (Exception e) {
>>     LOGGER.info(e);
>>   }
>> }
>> ```
>>
>> by the way, i totally love the approach of jooq here.
>> I got baffled today when i realized that the JTA Transactional Annotation 
>> does not catch checked exceptions per default and does not rollback in that 
>> case.
>> Maybe they do it for a good reason, but in such a situation i think it 
>> can be a good idea to just ditch JTA transaction to write something by 
>> oneself.
>>
>> I only sometimes fear that that quarkus guys, build some kind of 
>> Developer UI on the existing Stuff like Transactional, and when i use jooq 
>> transactions, 
>> i may not be able to profit from it, but the additional control in 
>> regards to the code is worth it i think.
>>
>> Bernd Huber schrieb am Sonntag, 24. März 2024 um 10:09:54 UTC:
>>
>>> Hello guys,
>>>
>>> many of us possibly work on SaaS server applications,
>>> where we often have the following layers:
>>>
>>> - Manager/Services Layer (Opens up transactions)
>>> - DAO Layer (Interacts with the database)
>>>
>>> i now would like to make use of jooqs nested transactions, as they are 
>>> described in: https://blog.jooq.org/nested-transactions-in-jooq/ but i 
>>> also would like to pass this "jooq-context" of each transaction (with 
>>> additional data typical for SaaS like tenantId, languageId, ...) into the 
>>> dao-layer, so the dao-instances will only work on this transaction and have 
>>> the additional data (tenantId,...) available for filtering etc.
>>>
>>> i have already written a class that implements the "Try-With-Resources" 
>>> pattern, which works correctly. See: 
>>> https://github.com/funkrusher/fk-framework-quarkus-jooq/blob/main/fk_core/src/main/java/org/fk/core/jooq/JooqContext.java
>>>
>>> i can use it as follows in the manager layer of my app:
>>>
>>> ```java
>>> public void deleteAndInsert(List<AuthorRecord> insertAuthors) {
>>>
>>>   // transaction1
>>>   try (JooqContext t1JooqContext = 
>>> jooqContextFactory.createJooqContext(requestContext)) {
>>>
>>>     AuthorDao t1AuthorDao = daoFactory.createAuthorDao(t1JooqContext);
>>>     List<AuthorRecord> existingAuthors = 
>>> t1AuthorDao.selectSomeAuthors(insertAuthors);
>>>
>>>     // transaction2
>>>     try (JooqContext t2JooqContext = 
>>> jooqContextFactory.createJooqContext(requestContext)) {
>>>       AuthorDao t2AuthorDao = daoFactory.createAuthorDao(t2JooqContext);
>>>       t2AuthorDao.deleteByAuthorIds(existingAuthors);
>>>       t2JooqContext.commit();
>>>     }
>>>
>>>     // transaction3
>>>     try {
>>>       try (JooqContext t3JooqContext = 
>>> jooqContextFactory.createJooqContext(requestContext)) {
>>>         AuthorDao t3AuthorDao = 
>>> daoFactory.createProductRecordDAO(t3JooqContext);
>>>         t3AuthorDao.insert(insertAuthors);
>>>         t3JooqContext.commit();
>>>       }
>>>     } catch (Exception e) {
>>>       LOGGER.info(e);
>>>     }
>>>
>>>   } catch (Exception e) {
>>>     e.printStackTrace();
>>>   }
>>> }
>>> ```
>>>
>>> within the JooqContext class i work with jooqs:
>>> - dsl.startTransaction (at start of try-with-resources)
>>> - dsl.commit (must be called explicit from outside)
>>> - dsl.rollback when the try-block has not been completed with a "commit" 
>>> call.
>>>
>>> the only problem i currently have is, that i explicitly need to "commit" 
>>> every transaction at the end of my Try-With-Resources block.
>>>
>>> I now want to ask you guys:
>>> - is there a better way to achieve what i need (Manager-Layer and 
>>> Dao-Layer separation with shared request-data like tenantId + transaction 
>>> management in Manager-Layer)
>>>
>>> and if its ok what i do, 
>>> is there a way to make the try-with-resources call commit automatically 
>>> at the end of the Try-Block.
>>>
>>> best regards,
>>>
>>> Bernd
>>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "jOOQ User Group" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to jooq-user+...@googlegroups.com.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/jooq-user/18163c0d-8cbe-4f92-93dd-d98ab3f4eda0n%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/jooq-user/18163c0d-8cbe-4f92-93dd-d98ab3f4eda0n%40googlegroups.com?utm_medium=email&utm_source=footer>
>> .
>>
>

-- 
You received this message because you are subscribed to the Google Groups "jOOQ 
User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to jooq-user+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/jooq-user/d465bb3e-3779-4c7f-9aa9-958490b0055cn%40googlegroups.com.

Reply via email to