> setters, it's easy to generate a method that just calls all of them: [...]
That is a nice idea. Care to contribute? :-)
In essence, the code-generator could do this:
- If records AND pojos are generated, it would generate into(POJO) and
from(POJO) methods
- If records AND interfaces are generated, it would generate
into(IFace) and from(IFace) methods
The second rule would override the first. I'll file this as feature
request #1689
https://github.com/jOOQ/jOOQ/issues/1689
Besides, from your logic, I'd say that adding a general <E> E
Record.into(E) method might be a useful addition, copying data into
previously instanciated custom POJO types:
https://github.com/jOOQ/jOOQ/issues/1688
> Maybe it would make sense to combine all columns related to the PK into a PK
> Java type, so the whole PK gets a single "has changed" flag.
I have thought about this before. Having multi-column primary keys
modelled as a single object would help resolve some API issues that
can currently not be resolved - e.g. generated DAOs don't really
support multi-column PKs.
Adding such PK support might look simple at first, but the
corresponding foreign keys might also have to be modelled accordingly,
I guess. I'm not sure yet, if I want to go down that road. Anyway,
let's track the idea as #1690:
https://github.com/jOOQ/jOOQ/issues/1690
> But I have a feeling that this could cause nasty corner cases when someone
> tries to manipulate the individual columns with setValue(field, ...);
The PK Java object would have to encapsulate the same behaviour
today's org.jooq.impl.Value internal object encapsulates. I.e.
changing one PK column would mean that the whole PK can be considered
as "changed". This is already the case today, although the information
is distributed across multiple org.jooq.impl.Value objects.
Record.setValue() has all the necessary information to update any PK's
internal "changed" flags, should a PK member be changed individually
through other API methods. With a sufficient number of test cases, I
don't think that would be a problem.
> Well, Hibernate solves this like so: If the PK is null, the identity
> generator is started to assign a PK (well, I simplify but you get the idea)
> and an INSERT will happen. If the PK is not null, it will UPDATE.
Yes, I know this behaviour by Hibernate. In the early days of jOOQ, I
have evaluated it against other options.
> This feels natural because it uses the assumption that you can't have a
> PK unless the record has been read from the DB. And if you have a PK,
> then the DB must already know about it.
This model might suit 90% of user needs. But jOOQ also accomodates
those 10% who generate PK values in Java (using UUID's, explicit
Oracle sequence calls, etc.). In those cases, the PK values are set
explicitly upon a Record with the intent of executing an INSERT, not
an UPDATE.
In other words, you *can* have a PK value that the DB does not yet
know about. The only way to be sure that the PK is already in the DB
is when the Record was actually fetched from the DB.
Now, of course, this leads to the inverse problem that you, as a user,
cannot set a PK value upon a (new) Record, without jOOQ assuming that
you intend to INSERT this Record.
> So maybe a good solution would be to modify jOOQ to support a similar behavior.
I prefer not to change that logic at this stage. It might break quite
a few applications.
> With my suggested changes in the Configuration class, it would be simple
> to add the PK generator to it. Everything else should then be a purely
> internal change of the logic.
I'm still exploring alternatives of supporting PK generators in
Record.store() calls. I also like the idea to support a central
authority for this in the Configuration / Settings objects. In fact, I
would like to go much farther and support something like an
org.jooq.Trigger type, that can be configured centrally in the
Configuration. This trigger type could then be parameterised to listen
to any type of statement event. I would like to get inspiration from
standard SQL triggers, which feature:
- Scope (i.e. listening to all events, or just to events for some tables)
- Statement type (i.e. listening to any statement, or just inserts/updates, etc)
- Conditions (i.e. triggered always, or just when some condition is met)
- Before / After
- etc.
Such triggers would be implemented as ExecuteListeners.
Let's track this, too:
https://github.com/jOOQ/jOOQ/issues/1691
Cheers
Lukas