I did some reading on the current state of jOOQ and how to handle updating changed records. I thought I had a fair grasp on it, but I've hit a bit of a blocker, and I'd love some assistance.
What I'm seeing is if I do a Table.fetch of a record into an UpdatableRecord, and I then try to update that record with the data from a pojo for it using record.fetch(), the ID field "goes away". It is no longer in the values and original arrays which means that reset() doesn't work on it, and I can't find a way to be able to update the record back into the DB.
Here is a sample of the code I was trying to get to work. Please note the comments in the middle that indicate the specifics of the problem.
DB1.ctx.fetch(DB1.T.SOURCETABLE).intoMap(DB1.T.SOURCETABLE.ID, SourcePojo.class))
final Collection<SourcePojo> sourcePojoRecords = (Collection<SourcePojo>) relationsMap.get(SourcePojo.class.getSimpleName()).values();
sourcePojoRecords
.forEach(sourcePojo -> {
Entity<SourcePojo> destinationPojo;
Table<? extends UpdatableRecord<?>> destinationTable;
Field<?> destinationId;
switch (sourcePojo.getSourcePojoType()) {
case 1:
destinationPojo = new DestinationsA();
destinationTable = DB2.T.DESTINATIONTABLE_A;
destinationId = DB2.T.DESTINATIONTABLE_A.ID;
break;
case 2:
destinationPojo = new DestinationsInfrastructure();
destinationTable = DB2.T.DESTINATIONTABLE_B;
destinationId = DB2.T.DESTINATIONTABLE_B.ID;
break;
case 3:
destinationPojo = new DestinationsInfrastructureMcus();
destinationTable = DB2.T.DESTINATIONTABLE_B_ALT;
destinationId = DB2.T.DESTINATIONTABLE_B_ALT.ID;
break;
default: // Other
destinationPojo = new Destinations();
destinationTable = DB2.T.DESTINATIONTABLE_OTHER;
destinationId = DB2.T.DESTINATIONTABLE_OTHER.ID;
break;
}
destinationPojo.migrateFrom(sourcePojo);
// At this point, destinationRecord has values[0] which is the ID, and it is valid.
UpdatableRecord<?> destinationRecord = DB2.ctx.fetchAny(destinationTable, DSL.condition("(destination_key->>'id')::int = ?", sourcePojo.getId()));
if (destinationRecord == null) {
destinationRecord = DB2.ctx.newRecord(destinationTable, destinationPojo);
} else {
// This call works fine even though it is basically a no-op since value[0] and original[0] match.
destinationRecord.reset(destinationId);
// After the call to from(), the destinationRecord no longer has value[0] or original[0].
// The changed bitset shows field[1] as the first change.
destinationRecord.from(destinationPojo);
// This throws an error that there is no such field in the database.
destinationRecord.reset(destinationId);
// The rest of this code seems to work fine. The other fields are compared and the changed flag is removed if they are identical.
UpdatableRecord<?> finalDestinationRecord = destinationRecord;
Arrays.stream(destinationRecord.fields()).forEach(field -> {
if (Objects.equals(finalDestinationRecord.original(field), finalDestinationRecord.get(field))) {
finalDestinationRecord.changed(field, false);
}
});
}
if (destinationRecord.changed()) {
// If I try to call store() without doing anything to the destinationId, it will insert it as a new record since it has no ID.
log.info("Updating Destination (ID: {} Key: {}) with changes.", destinationPojo.getId(), sourcePojo.getEntityKey().toJson());
destinationRecord.store();
} else {
log.info("Skipping update for unchanged Destination (ID: {} Key: {}) with changes.", destinationPojo.getId(), sourcePojo.getEntityKey().toJson());
}
});