Hi Lukas,
I have a table USERSETTINGS in which I want to insert data via
onDuplicateKeyUpdate in PostgreSQL.
If a row with the primary key combination (username,key) already exists, UPDATE
should be used instead of INSERT. Everything works fine until I noticed that
the modified_at field is not set during the optimistic locking handling. My
current implementation looks like this:
UsersettingsRecord dbRecord = jooq.newRecord(USERSETTINGS,
usersettings);
jooq.insertInto(USERSETTINGS).set(dbRecord).onDuplicateKeyUpdate().set(dbRecord).execute();
a) if I manually set the date before the insertInto/onDuplicateKeyUpdate
dbRecord.setModifiedAt(LocalDateTime.now());
everything works. But I wanted to avoid that.
b) if I use dbRecord.merge() instead of jooq.insertInto... it doesn't work
anymore. There are duplicate-key exceptions during INSERT, i.e. the
onDuplicateKeyUpdate mechanism does not work at all. This is probably due to
the UpdatableRecordImpl.lockValuePresent:
// [#10050] A lock value is present if we either have locking columns or if
the record was fetched from the database
return getRecordVersion() != null
// NULL in my case
|| getRecordTimestamp() != null
// not NULL in my case
|| getTable().getRecordVersion() == null //
NULL in my case
&& getTable().getRecordTimestamp() == null // not NULL in
my case
&& fetched;
// true in my case
The whole expression evaluates to FALSE in my case which leads in method
UpdatableRecordImpl.storeMerge0
always to the call of storeInsert0 instead of storeUpdate0.
Is there a bug in UpdatableRecordImpl.lockValuePresent or how can I profit from
updateOnDuplicateKeyUpdate while using records instead of insertInto(…) ?
Kind regards
Dominik
This is the table:
CREATE TABLE
usersettings
(
username CHARACTER VARYING NOT NULL,
KEY CHARACTER VARYING NOT NULL,
value CHARACTER VARYING,
modified_at TIMESTAMP(6) WITHOUT TIME ZONE,
PRIMARY KEY (username, KEY)
);
And her a nearly complete JBANG example:
//DEPS org.jooq:jooq:${jooq.version:RELEASE}
//DEPS org.postgresql:postgresql:${postgresql.version:RELEASE}
//DEPS org.slf4j:slf4j-api:1.7.32
//DEPS ch.qos.logback:logback-classic:1.2.4
//SOURCES de/hub28/steel42/generated/**
import static org.jooq.impl.DSL.*;
import static de.hub28.steel42.generated.Tables.*;
import org.jooq.*;
import org.jooq.conf.*;
import java.io.*;
import java.io.File;
import java.sql.*;;
import java.util.*;
import java.time.LocalDateTime;
import de.hub28.steel42.generated.tables.records.*;
import de.hub28.steel42.generated.tables.pojos.*;
public class InsertOnDuplicate {
private static DSLContext jooq;
public static void main(String[] args) throws Exception {
DriverManager.registerDriver((Driver)
Class.forName("org.postgresql.Driver").newInstance());
String url = "jdbc:postgresql://127.0.0.1:5432/steel42";
Connection conn = DriverManager.getConnection(url);
Settings settings = new Settings()
.withRenderNameCase(RenderNameCase.AS_IS)
.withRenderQuotedNames(RenderQuotedNames.EXPLICIT_DEFAULT_QUOTED)
.withRenderSchema(false)
.withUpdateRecordTimestamp(true)
.withExecuteWithOptimisticLocking(true) // nutzt die als
'recordTimestampFields' definierten Spalten 'modified_at'
.withReturnAllOnUpdatableRecord(true)
.withExecuteLogging(true);
jooq = using(conn, settings);
// System.out.println(jooq.toString());
Usersettings usersettings = new Usersettings();
usersettings.setUsername("dominik");
usersettings.setKey("KEY");
usersettings.setValue("VALUE");
dontWorkWithoutManuallySet(usersettings);
dontWorkWithRecordMerge(usersettings);
fix(usersettings);
}
private static void dontWorkWithoutManuallySet(Usersettings
usersettings ) {
UsersettingsRecord dbRecord = jooq.newRecord(USERSETTINGS,
usersettings);
jooq.insertInto(USERSETTINGS).set(dbRecord).onDuplicateKeyUpdate().set(dbRecord).execute();
jooq.selectFrom(USERSETTINGS).where(USERSETTINGS.USERNAME.eq("dominik")).fetch();
//dbRecord.delete();
}
private static void dontWorkWithRecordMerge(Usersettings usersettings )
{
UsersettingsRecord dbRecord = jooq.newRecord(USERSETTINGS,
usersettings);
dbRecord.merge();
}
private static void fix(Usersettings usersettings ) {
UsersettingsRecord dbRecord = jooq.newRecord(USERSETTINGS,
usersettings);
dbRecord.setModifiedAt(LocalDateTime.now()); // optimistic lock geht
hier nicht
jooq.insertInto(USERSETTINGS).set(dbRecord).onDuplicateKeyUpdate().set(dbRecord).execute();
jooq.selectFrom(USERSETTINGS).where(USERSETTINGS.USERNAME.eq("dominik")).fetch();
dbRecord.delete();
}
}
--
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/jooq-user/EBF08891-9BEF-4B47-A9E6-BF048CD4D3B1%40googlemail.com.