Definitively answering the question "where in my codebase do I use this table" - is it possible to centralise table references?

15 views
Skip to first unread message

shorn....@gmail.com

unread,
Oct 16, 2017, 3:03:53 AM10/16/17
to jOOQ User Group
Sometimes, I just want to answer the question "where do I use this table"?

I'd like to be able to go to the place where that table is defined and do a "show usages".  
But my IDE (IntelliJ) will only find the references to the specific kind of reference I'm using, JOOQ declares these "table references" in multiple places.

That I know of, there are at least three ways table (or views, etc.) references are declared in JOOQ.

1) use the static constant in Tables class -
table = example.db.Tables.ACCOUNT


2) static constant in the concrete TableImpl subclass -
table = example.db.tables.Account


3) instantiate the concrete subclass -
table = new Account()

When I do "find usages" in IntelliJ, it only finds references to the one specific way that my cursor happens to be on.

Does anyone know of a way where I can ask my IDE "what are all the places the account table is used in the codebase".
I'm looking for a fast / easy way here that I can do this rapidly, many times on all sorts of different objects - "grepping" or other text based scripting is really not what I want.

Failing an IDE way (which I think might not exist) - is there a JOOQ feature that can help with this?

For example, can I tell JOOQ not to generate the static constants, such that using the Account constructor is the only way to refer to the table?
It would be less convenient - but that's fine, being able to easily know all places in the code that refer to a table would be worth that price to me.
Failing existince of a JOOQ feature to help with this, it wouldn't be too hard for me to remove the features during the code generation stage - but would that even do the job though?  Are the above three "reference types" the only code-based ways to refer to DB objects, or other there other ways I don't know about yet?

----

Yes, I understand this won't help me with views/functions, etc. that are textually defined to use tables etc.
I'm aware I could put in place some kind of static analysis to enforce usage of a single type of table reference.  But I'm asking if I can use JOOQ to eliminate the possibility of using different types.

I am using JOOQ 3.9.3 and Postgres.  
My config settings are:

relations("true")     
records("true")       
fluentSetters("true") 
deprecated("false")
pojos("false")
immutablePojos("false")
pojosEqualsAndHashCode("true")


Lukas Eder

unread,
Oct 18, 2017, 8:05:13 AM10/18/17
to jooq...@googlegroups.com
Hi Shorn,

Thank you very much for your message.

That's a very good question, and unfortunately, there's not a very easy answer. In particular, you probably left out at least another case of where your table could be used, namely where the AccountRecord is used, or the Account (POJO).

If you're looking only for DSL API usage (without the records, POJOs, etc.), then I'd go for the constructor calls of the table and recurse in the call hierarchy, because ultimately, those static constants:

- Reference each other as in case 1)
- Create a new table instance, as in case 2)

More comments inline

2017-10-16 1:48 GMT+02:00 <shorn....@gmail.com>:
For example, can I tell JOOQ not to generate the static constants, such that using the Account constructor is the only way to refer to the table?

Yes, you can specify <globalObjectReferences>false</globalObjectReferences> to turn off all references such as the ones in Tables.java, or <globalTableReferences>false</globalTableReferences> to turn off just the ones in Tables.java

I realise that the above flags are not documented on this page:

For details, see the XSD:
 
Failing existince of a JOOQ feature to help with this, it wouldn't be too hard for me to remove the features during the code generation stage - but would that even do the job though?  Are the above three "reference types" the only code-based ways to refer to DB objects, or other there other ways I don't know about yet?

Ultimately, you have to track the constructor calls. All constructors are essential: One is used to create the static table reference (or your own references if you call it yourself), and the other is used to alias the table, which you should also match in your search.

Of course, once you start working with the meta data APIs, you could also access tables from:

- Constraints
- org.jooq.Meta
- plain SQL API
- InformationSchema
- Other ways?

Yes, I understand this won't help me with views/functions, etc. that are textually defined to use tables etc.

That's an interesting thought, though. I wonder if jOOQ could offer something in this area, in the long term.
 
I'm aware I could put in place some kind of static analysis to enforce usage of a single type of table reference.  But I'm asking if I can use JOOQ to eliminate the possibility of using different types.

One more thing: You could patch the code generator to generate only private table constructors. That way, you couldn't instantiate them yourself anymore and you'd be forced to use the static singleton instance. Together with turning off the <globalTableReferences/>, you'd have a single point of contact with each table.

Hope this helps,
Lukas

shorn....@gmail.com

unread,
Oct 30, 2017, 8:54:05 PM10/30/17
to jOOQ User Group
Thanks for taking the time to write this up.

I did do the globalTableReferences thing.  It at least eliminates the annoyance I was feeling whenever I wrote some JOOQ code - I *knew* I was using thing inconsistently but I didn't want to setup  a static analysis tool.  I didn't really care which one was used (though it was confusing and annoying at first when figuring out that it didn't matter).

When I tried to do the globalObjectReferences instead, I ran into a problem with Sequences - the global object ref is the *only* specific code reference JOOQ generates.  

One thing I did do in my own project structure was to factor out the JOOQ generated code to its own Gradle sub-project that my server depends on.
This helps me quickly filter out all the JOOQ internal references when I'm scanning the results in my IDE.

I have "pojos=false", so now I do searches by looking for:
- Table.EXAMPLE
- Example() ctor
- ExampleRecord

This works well enough for me.
Thanks for your help.

Lukas Eder

unread,
Oct 31, 2017, 5:01:24 AM10/31/17
to jooq...@googlegroups.com
2017-10-31 1:54 GMT+01:00 <shorn....@gmail.com>:
Thanks for taking the time to write this up.

I did do the globalTableReferences thing.  It at least eliminates the annoyance I was feeling whenever I wrote some JOOQ code - I *knew* I was using thing inconsistently but I didn't want to setup  a static analysis tool.  I didn't really care which one was used (though it was confusing and annoying at first when figuring out that it didn't matter).

When I tried to do the globalObjectReferences instead, I ran into a problem with Sequences - the global object ref is the *only* specific code reference JOOQ generates.  

Yes, that's the sledge hammer. There's also <globalTableReferences/>...
 
One thing I did do in my own project structure was to factor out the JOOQ generated code to its own Gradle sub-project that my server depends on.
This helps me quickly filter out all the JOOQ internal references when I'm scanning the results in my IDE.

That's certainly a good idea. Also, special package namespaces can help to do that, visually. Depending on how the IDE works, of course.

Thanks,
Lukas
Reply all
Reply to author
Forward
0 new messages