Indexes.java refers to private fields

30 views
Skip to first unread message

Khun Yee Fung

unread,
Feb 28, 2024, 4:44:01 PMFeb 28
to jOOQ User Group
Apologies if this has been asked before. I could find any previous messages discussing this issue. If it has been discussed before, please point me to the discussion.

I just subscribed to the express version of jOOQ because I really wanted the primary keys to be their own types. When I added 

<includePrimaryKeys>true</includePrimaryKeys>
<includeIndexes>true</includeIndexes>
<includeForeignKeys>true</includeForeignKeys>
<includeUniqueKeys>true</includeUniqueKeys>
<embeddableUniqueKeys>.*</embeddableUniqueKeys>
<embeddablePrimaryKeys>.*</embeddablePrimaryKeys>

to my config file, I got errors when I compile the generated code. These errors in the Indexes.java have the following pattern:

error: FIELD has private access in DBTable

Basically one per index that I have in the database. I am using version 3.19.5 express, postgres 16.2.

What did I do wrong, either in the config file, or any other places?

I have other errors when I don't generate indexes. But these errors might all stem from the same issues that I have.

Any hints or help would be appreciated.

Thanks in advance.

Lukas Eder

unread,
Feb 29, 2024, 2:33:05 AMFeb 29
to jooq...@googlegroups.com
Hello,

Thanks for your report. This isn't a known issue yet. I've created a bug to track this:

What other errors are you getting if you don't generate the indexes? There only few reasons why you need the indexes in generated code, so the simplest workaround for the above issue would be to turn off the generation of indexes

Best Regards,
Lukas

--
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/7f4e2e2c-5b26-43b6-a277-06398024a95bn%40googlegroups.com.

Khun Yee Fung

unread,
Feb 29, 2024, 9:33:38 AMFeb 29
to jOOQ User Group
Thank you very much for the information.

I do not need indexes in my code, that is for sure. I included it because the default seems to be "true". So, initially, this is what I have.

<embeddableUniqueKeys>.*</embeddableUniqueKeys>
<embeddablePrimaryKeys>.*</embeddablePrimaryKeys>

And I would get the same private field access compilation errors.

So, I disabled generating indexes. 

<!-- <includePrimaryKeys>true</includePrimaryKeys>-->
<includeIndexes>false</includeIndexes>
<!-- <includeForeignKeys>true</includeForeignKeys>-->
<!-- <includeUniqueKeys>true</includeUniqueKeys>-->
<embeddableUniqueKeys>.*</embeddableUniqueKeys>
<embeddablePrimaryKeys>.*</embeddablePrimaryKeys>

The compilation errors I get are now in the form of

cannot find symbol
    super(DBAbc.ABC.REL_ABC_EFG.getDataType().getRow());
                   ^
    symbol:   variable REL_ABC_EFG
    location: variable ABC of type DBAbc


Where ABC and EFG are two tables, where EFG has a foreign key from ABC.

I did check different instances of the class "DBAbc", and they don't have the "REL" fields. On the other hand, this is the weird thing I found,

DBEfg has that REL field. So, REL_ABC_EFG   is in DBEfg, not in DBAbc.

I then changed the config again to

<includePrimaryKeys>true</includePrimaryKeys>
<includeIndexes>false</includeIndexes>
<includeForeignKeys>true</includeForeignKeys>
<includeUniqueKeys>true</includeUniqueKeys>
<embeddableUniqueKeys>.*</embeddableUniqueKeys>
<embeddablePrimaryKeys>.*</embeddablePrimaryKeys>

Same errors, but the compilation order has changed.

Thanks.

Lukas Eder

unread,
Feb 29, 2024, 9:39:18 AMFeb 29
to jooq...@googlegroups.com
Thanks for the follow up details. That seems to be another bug. Can you please post a complete reproducer including:

- The CREATE TABLE for all relevant tables
- The complete code generation configuration

On github, we usually ask users to provide a minimal, complete, verifiable reproducer based on our template:

While it isn't always necessary to use this template, it has proven to be very useful in making sure a problem can be reproduced.

Looking forward to hearing from you again,
Lukas

Khun Yee Fung

unread,
Feb 29, 2024, 2:30:37 PMFeb 29
to jOOQ User Group
Due to company policy, unfortunately, I can't simply just upload the DDL of the schema that caused the issues. So, I tried to recreate the relationships to reproduce the errors. I tried up to 30 tables, generated in various ways to try to mimic the error. No dice. So, it seems the complexity of the schema plays a role in the generation error. I will continue to try to find a minimal set of tables that will produce the issue consistently.

This error is not universal, meaning that it does not happen for all tables, only a select few. In the over 300 tables in the schema that I have, I have this error for around 20 tables. The code generated for the rest is fine, using the right primary key. There must be a common pattern for these 20 odd tables. Unfortunately, I can't find the common pattern yet. Once I find it, I should be able to come up with a minimal set. Then I will file the report.

--

Then, I decided to "correct" the errors with a script so that I could continue the investigation on whether the code generated would be useful for my purpose. After the "corrections", the code compiles. To my surprise, after doing the changes, I have no access to the primary and foreign keys of the generated table classes any more. So, ABC.ABC_ID is now a private field. Which is fine, I guess, but I don't know how to compare keys in a join as I don't see a field that is public that I can use. I am quite sure I am just ignorant of the right way to do updates, inserts, and joins once I decide to have the embedded keys generated. I will try to find out what is the new ways to do these operations with the code generated being rather different from before. However, to have to change all the occurrences of how keys are used for all the tables in all the places in our system might be a time-consuming task. This can't be correct, right?  Correcting the comparison where one side is a Integer or a String or what have you is fine, as that is the whole point of having one type for each key. They are also mostly in the WHERE clause as well. Not being to compare ABC.ABC_ID and EFG.ABC_ID is a bit different, as this is pervasive wherever I have a join.

I would appreciate it very much if I can be pointed to the section of the documentation where it talks about how keys are used once I have these private key fields.

So, I had this before, for example:

create.select()
.from(ABC)
.join(EFG).on(ABC.ABC_ID.equal(EFG.ABC_ID))
.where(ABC.NAME.equal("Smith"))
.fetch();

Now it would say ABC_ID is a private field (back to the error I got when I tried to generate code for the indexes), which it is. My problem is that I don't know what to substitute ABC_ID with.

Thanks in advance for any insight into how these DML should now be constructed!

My learning continues, of course, this being my second day after subscribing to the express edition.

Lukas Eder

unread,
Mar 1, 2024, 4:34:14 AMMar 1
to jooq...@googlegroups.com
On Thu, Feb 29, 2024 at 8:30 PM Khun Yee Fung <khunye...@gmail.com> wrote:
Due to company policy, unfortunately, I can't simply just upload the DDL of the schema that caused the issues. So, I tried to recreate the relationships to reproduce the errors. I tried up to 30 tables, generated in various ways to try to mimic the error. No dice. So, it seems the complexity of the schema plays a role in the generation error. I will continue to try to find a minimal set of tables that will produce the issue consistently.

This error is not universal, meaning that it does not happen for all tables, only a select few. In the over 300 tables in the schema that I have, I have this error for around 20 tables. The code generated for the rest is fine, using the right primary key. There must be a common pattern for these 20 odd tables. Unfortunately, I can't find the common pattern yet. Once I find it, I should be able to come up with a minimal set. Then I will file the report.

I understand. Thanks a lot for looking into this. I'll continue checking on my side how this could happen. My main hypothesis is that there's a naming problem of the embeddable column, i.e. the table where the embeddable key is declared uses a different name for the embeddable than the reference in the generated record. Can you confirm this is the case? But that wouldn't explain yet why this happens.
 
Then, I decided to "correct" the errors with a script so that I could continue the investigation on whether the code generated would be useful for my purpose. After the "corrections", the code compiles. To my surprise, after doing the changes, I have no access to the primary and foreign keys of the generated table classes any more. So, ABC.ABC_ID is now a private field. Which is fine, I guess, but I don't know how to compare keys in a join as I don't see a field that is public that I can use. I am quite sure I am just ignorant of the right way to do updates, inserts, and joins once I decide to have the embedded keys generated. I will try to find out what is the new ways to do these operations with the code generated being rather different from before. However, to have to change all the occurrences of how keys are used for all the tables in all the places in our system might be a time-consuming task. This can't be correct, right?  Correcting the comparison where one side is a Integer or a String or what have you is fine, as that is the whole point of having one type for each key. They are also mostly in the WHERE clause as well. Not being to compare ABC.ABC_ID and EFG.ABC_ID is a bit different, as this is pervasive wherever I have a join.

Embeddable keys automatically apply "field replacement":

The point is that you will never want to compare individual fields of an embeddable key anymore. You will always want to treat the embeddable key as a whole. So, rather than comparing ABC.ABC_ID and EFG.ABC_ID individually, you will compare ABC.KEY and EFG.KEY (or whatever they're called). This improves type safety of your queries, as you can't compare any BIGINT columns randomly anymore, for example.

Can you show an example schema and query where you still need access to the underlying columns? Perhaps we should add another flag to allow for opting out of this code generation behaviour, though I do believe this is the right default, and what most people want. The main reason why embeddable keys were implemented was precisely this, people were asking for a domain type per key, to get the added type safety.

I hope this helps
Lukas

Khun Yee Fung

unread,
Mar 3, 2024, 3:43:27 PMMar 3
to jOOQ User Group
Got it. Will see when and how we can refactor the existing code base to fit this.

Thanks.
Reply all
Reply to author
Forward
0 new messages