--
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.
For more options, visit https://groups.google.com/groups/opt_out.
Hello,A similar problem has been reported before:It has lead to this feature requests (among others):
In the mean time, your workaround is one way to do this, another would be this:final Record inputRec = sql.newRecord(USER);inputRec.from(user);for (Field<?> f : inputRec.fields()) {
if (inputRec.getValue(f) == null)inputRec.changed(false);}inputRec.store();
On Thursday, October 17, 2013 10:59:03 AM UTC+2, Lukas Eder wrote:Hello,A similar problem has been reported before:It has lead to this feature requests (among others):I was quite convinced that I'm not the first one with this issue, but I unfortunately failed to pinpoint the earlier posts, sorry :)
In the mean time, your workaround is one way to do this, another would be this:final Record inputRec = sql.newRecord(USER);inputRec.from(user);for (Field<?> f : inputRec.fields()) {
if (inputRec.getValue(f) == null)inputRec.changed(false);}inputRec.store();Great, I was experimenting with this approach involving changed. However, I overlooked the store method and used creat.insertInto(...), which always inserted nulls regardless of their changed status.
create.newRecord(u)
.from(user)
.eachField((ctx) -> {if (ctx.rec().getValue(ctx.field()) == null) ctx.rec().changed(ctx.field(), false);})
.store();
;-)
I've come across a related problem to the above. Now I need to to a standard UPDATE...SET...WHERE, but I've got more than one type of change--for example:(passwordChange?sql.update(u).set(u.PASSWORD, user.getPassword()).set(u.SALT, user.getSalt()): sql.update(u).set(u.FIRST_NAME, user.getFirstName()).set(u.LAST_NAME, user.getLastName()).set(u.EMAIL, user.getEmail())).where(u.USERNAME.eq(user.getUsername())).execute();
As you can see, there's still a bit of boilerplate there (in the set invocations). I would like to use a similar approach as above with records (automatically select any non-null value from the user POJO as a field to be updated), but I don't know how to incorporate the WHERE part when storing a record (username is not the primary key, but it's a NOT NULL UNIQUE column). I'm not in favor of an extra fetch from the DB to get the primary key when a direct UPDATE is enough.
Hi Marko,
I think it is difficult to avoid this boilerplate in a sensible way. There might be some potential for convenience methods on the generated UNIQUE contraint in Keys.java, e.g. UniqueKey.eq(user.getUsername()). But I wonder how well such convenience methods would be adopted.
Note, there is DSLContext.executeUpdate(R, Condition):This might help you generate an UPDATE statement with a custom predicate based on a non-primary unique key, although you'd still have to handle nulls yourself.
Hi Lukas,
On Monday, October 21, 2013 11:43:56 AM UTC+2, Lukas Eder wrote:Hi Marko,I think it is difficult to avoid this boilerplate in a sensible way. There might be some potential for convenience methods on the generated UNIQUE contraint in Keys.java, e.g. UniqueKey.eq(user.getUsername()). But I wonder how well such convenience methods would be adopted.I was just looking how to associate e.g. the username field with the username property in the POJO (which is an obvious link and I consider it boilerplate if I have to write it out).
The approach from my post above gives me that fairly cleanly:final Record rec = sql.newRecord(u);rec.from(user);final Map<Field<?>, Object> toUpdate = new HashMap<>();for (Field<?> f : rec.fields()) {if (f == u.USERNAME) continue;final Object v = rec.getValue(f);if (v != null) toUpdate.put(f, v);}sql.update(u).set(toUpdate).where(u.USERNAME.eq(user.getUsername())).execute();although it's somewhat roundabout because it involves a Map instead of just a Record. Basically, I use a Record to do the reflection part (POJO -> Record) and then transfer the record to a Map with the logic which weeds out null fields and separates the "update these" fields from "where these match" fields.Note, there is DSLContext.executeUpdate(R, Condition):This might help you generate an UPDATE statement with a custom predicate based on a non-primary unique key, although you'd still have to handle nulls yourself.This looks quite usable for my need! I think I can adapt the above code and avoid the Map. I'll see into it, thanks!-Marko
--
Hi Lukas,I think I'm still missing something regarding #2704: it seems to me that this issue is about fetching a record from the db, then updating it with incoming data from a request.
On the other hand, I am keen on avoiding any fetching: I want an unconditional UPDATE tableX SET (columns_to_update) WHERE (these_columns_match). The values for both column groups come from a JSON request, uniformly in a single map, and the service layer must know in advance which values belong to which group. Note that, in general, these_columns_match is not required to form a unique key: in that case many database record may be updated. This is the main reason why I don't want fetching, but even if they do form a unique key, I may want to perform bulk updates, where again fetching would hurt performance and complicate the logic.
All said, I am quite satisfied with the solution I already have and I believe I can improve on it using executeUpdate(R, Condition).