-
- Type Parameters:
R
- The record type
- All Superinterfaces:
Attachable
,Comparable<Record>
,Formattable
,Record
,Serializable
,TableRecord<R>
- All Known Implementing Classes:
UpdatableRecordImpl
public interface UpdatableRecord<R extends UpdatableRecord<R>> extends TableRecord<R>
A common interface for records that can be stored back to the database again.Any
Record
can be updatable, if- it represents a record from a table or view - a
TableRecord
- its underlying table or view has a "main unique key", i.e. a primary key or at least one unique key
The "main unique key" is used by jOOQ to perform the various operations that can be performed on an
UpdatableRecord
:-
delete()
: Deleting the record -
refresh()
: Refreshing the records attributes (or loading it for the first time) -
store()
: Storing the record to the database. This executes either anINSERT
or anUPDATE
statement
UpdatableRecords
areAttachable
, which means that they hold an underlyingConfiguration
that they can be detached from. They can also be instantiated without any underlyingConfiguration
, in case of which they have to be attached first, in order to be refreshed, stored, or deleted.- Author:
- Lukas Eder
-
-
Method Summary
All Methods Instance Methods Abstract Methods Modifier and Type Method Description R
copy()
Duplicate this record (in memory) and reset all fields from the primary key or main unique key, such that a subsequent call tostore()
will result in anINSERT
statement.int
delete()
Deletes this record from the database, based on the value of the primary key or main unique key.<O extends TableRecord<O>>
OfetchChild(ForeignKey<O,R> key)
Fetch a child record of this record, given a foreign key.<O extends TableRecord<O>>
Result<O>fetchChildren(ForeignKey<O,R> key)
Fetch child records of this record, given a foreign key.int
insert()
Store this record back to the database using anINSERT
statement.int
insert(Collection<? extends Field<?>> fields)
Store parts of this record to the database using anINSERT
statement.int
insert(Field<?>... fields)
Store parts of this record to the database using anINSERT
statement.Record
key()
A Record copy holding values for theTable.getPrimaryKey()
.void
refresh()
Refresh this record from the database.void
refresh(Collection<? extends Field<?>> fields)
Refresh parts of this record from the database.void
refresh(Field<?>... fields)
Refresh parts of this record from the database.int
store()
Store this record back to the database.int
store(Collection<? extends Field<?>> fields)
Store parts of this record to the database.int
store(Field<?>... fields)
Store parts of this record to the database.int
update()
Store this record back to the database using anUPDATE
statement.int
update(Collection<? extends Field<?>> fields)
Store parts of this record to the database using anUPDATE
statement.int
update(Field<?>... fields)
Store parts of this record to the database using anUPDATE
statement.-
Methods inherited from interface org.jooq.Attachable
attach, configuration, detach
-
Methods inherited from interface org.jooq.Formattable
format, format, format, format, format, format, format, format, format, formatChart, formatChart, formatChart, formatChart, formatChart, formatChart, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatCSV, formatHTML, formatHTML, formatHTML, formatInsert, formatInsert, formatInsert, formatInsert, formatInsert, formatInsert, formatJSON, formatJSON, formatJSON, formatJSON, formatJSON, formatJSON, formatXML, formatXML, formatXML, formatXML, formatXML, formatXML, intoXML, intoXML, intoXML, intoXML
-
Methods inherited from interface org.jooq.Record
changed, changed, changed, changed, changed, changed, changed, changed, changed, changed, compareTo, equals, field, field, field, field, fields, fields, fields, fields, fields, fieldsRow, from, from, from, from, from, fromArray, fromArray, fromArray, fromArray, fromArray, fromMap, fromMap, fromMap, fromMap, fromMap, get, get, get, get, get, get, get, get, get, get, get, get, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, getValue, hashCode, indexOf, indexOf, indexOf, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, into, intoArray, intoList, intoMap, intoResultSet, intoStream, map, original, original, original, original, reset, reset, reset, reset, reset, set, set, setValue, setValue, size, valuesRow
-
Methods inherited from interface org.jooq.TableRecord
fetchParent, getTable, original, with, with
-
-
-
-
Method Detail
-
key
Record key()
A Record copy holding values for theTable.getPrimaryKey()
.The returned record consists exactly of those fields as returned by the table's primary key:
Key.getFields()
.Generated subtypes may covariantly override this method to add more record type information. For instance, they may return
Record1
,Record2
, ...
-
store
int store() throws DataAccessException, DataChangedException
Store this record back to the database.Depending on the state of the primary key's value, an
insert()
or anupdate()
statement is executed.Statement type
- If this record was created by client code, an
INSERT
statement is executed - If this record was loaded by jOOQ and the primary key value was
changed, an
INSERT
statement is executed (unlessSettings.isUpdatablePrimaryKeys()
is set). jOOQ expects that primary key values will never change due to the principle of normalisation in RDBMS. So if client code changes primary key values, this is interpreted by jOOQ as client code wanting to duplicate this record. - If this record was loaded by jOOQ, and the primary key value was not
changed, an
UPDATE
statement is executed.
In either statement type, only those fields are inserted/updated, which had been explicitly set by client code, in order to allow for
DEFAULT
values to be applied by the underlying RDBMS. If no fields were modified, neither anUPDATE
nor anINSERT
will be executed.Automatic value generation
Use
insert()
orupdate()
to explicitly force either statement type.- IDENTITY columns
If there is an
IDENTITY
column defined on the record's underlying table (seeTable.getIdentity()
), then the auto-generatedIDENTITY
value is refreshed automatically onINSERT
's. Refreshing is done usingStatement.getGeneratedKeys()
, where this is supported by the JDBC driver. See alsoInsertQuery.getReturnedRecord()
for more details - VERSION and TIMESTAMP columns
jOOQ can auto-generate "version" and "timestamp" values that can be used for optimistic locking. If this is an
UpdatableRecord
and if this record returns fields for eitherTable.getRecordVersion()
orTable.getRecordTimestamp()
, then these values are set onto theINSERT
orUPDATE
statement being executed. On execution success, the generated values are set to this record. Use the code-generation configuration to specify naming patterns for auto-generated "version" and "timestamp" columns.Should you want to circumvent jOOQ-generated updates to these columns, you can render an
INSERT
orUPDATE
statement manually using the variousDSLContext.insertInto(Table)
,DSLContext.update(Table)
methods.
Optimistic locking
If an
UPDATE
statement is executed andSettings.isExecuteWithOptimisticLocking()
is set totrue
, then this record will first be compared with the latest state in the database. There are two modes of operation for optimistic locking:- With VERSION and/or TIMESTAMP columns configured
This is the preferred way of using optimistic locking in jOOQ. If this is an
UpdatableRecord
and if this record returns fields for eitherTable.getRecordVersion()
orTable.getRecordTimestamp()
, then these values are compared to the corresponding value in the database in theWHERE
clause of the executedDELETE
statement. - Without any specific column configurations
In order to compare this record with the latest state, the database record will be locked pessimistically using a
SELECT .. FOR UPDATE
statement. Not all databases support theFOR UPDATE
clause natively. Namely, the following databases will show slightly different behaviour:-
SQLDialect.CUBRID
andSQLDialect.SQLSERVER
: jOOQ will try to lock the database record using JDBC'sResultSet.TYPE_SCROLL_SENSITIVE
andResultSet.CONCUR_UPDATABLE
. -
SQLDialect.SQLITE
: No pessimistic locking is possible. Client code must assure that no race-conditions can occur between jOOQ's checking of database record state and the actualUPDATE
See
SelectQuery.setForUpdate(boolean)
for more details -
Statement examples
Possible statements are
-
INSERT INTO [table] ([modified fields, including keys]) VALUES ([modified values, including keys])
-
UPDATE [table] SET [modified fields = modified values, excluding keys] WHERE [key fields = key values] AND [version/timestamp fields = version/timestamp values]
Statement execution enforcement
If you want to enforce statement execution, regardless if the values in this record were changed, you can explicitly set the changed flags for all values with
Record.changed(boolean)
or for single values withRecord.changed(Field, boolean)
, prior to storing.This is the same as calling
record.store(record.fields())
- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the queryDataChangedException
- If optimistic locking is enabled and the record has already been changed/deleted in the database- See Also:
insert()
,update()
- If this record was created by client code, an
-
store
int store(Field<?>... fields) throws DataAccessException, DataChangedException
Store parts of this record to the database.- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the queryDataChangedException
- If optimistic locking is enabled and the record has already been changed/deleted in the database- See Also:
store()
,insert(Field...)
,update(Field...)
-
store
int store(Collection<? extends Field<?>> fields) throws DataAccessException, DataChangedException
Store parts of this record to the database.- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the queryDataChangedException
- If optimistic locking is enabled and the record has already been changed/deleted in the database- See Also:
store()
,insert(Field...)
,update(Field...)
-
insert
int insert() throws DataAccessException
Store this record back to the database using anINSERT
statement.This is the same as
store()
, except that anINSERT
statement (or no statement) will always be executed.If you want to enforce statement execution, regardless if the values in this record were changed, you can explicitly set the changed flags for all values with
Record.changed(boolean)
or for single values withRecord.changed(Field, boolean)
, prior to insertion.This is the same as calling
record.insert(record.fields())
- Specified by:
insert
in interfaceTableRecord<R extends UpdatableRecord<R>>
- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the query- See Also:
store()
-
insert
int insert(Field<?>... fields) throws DataAccessException
Store parts of this record to the database using anINSERT
statement.- Specified by:
insert
in interfaceTableRecord<R extends UpdatableRecord<R>>
- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the query- See Also:
insert()
-
insert
int insert(Collection<? extends Field<?>> fields) throws DataAccessException
Store parts of this record to the database using anINSERT
statement.- Specified by:
insert
in interfaceTableRecord<R extends UpdatableRecord<R>>
- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the query- See Also:
insert()
-
update
int update() throws DataAccessException, DataChangedException
Store this record back to the database using anUPDATE
statement.This is the same as
store()
, except that anUPDATE
statement (or no statement) will always be executed.If you want to enforce statement execution, regardless if the values in this record were changed, you can explicitly set the changed flags for all values with
Record.changed(boolean)
or for single values withRecord.changed(Field, boolean)
, prior to updating.This is the same as calling
record.update(record.fields())
- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the queryDataChangedException
- If optimistic locking is enabled and the record has already been changed/deleted in the database- See Also:
store()
-
update
int update(Field<?>... fields) throws DataAccessException, DataChangedException
Store parts of this record to the database using anUPDATE
statement.- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the queryDataChangedException
- If optimistic locking is enabled and the record has already been changed/deleted in the database- See Also:
update()
-
update
int update(Collection<? extends Field<?>> fields) throws DataAccessException, DataChangedException
Store parts of this record to the database using anUPDATE
statement.- Returns:
1
if the record was stored to the database.0
if storing was not necessary.- Throws:
DataAccessException
- if something went wrong executing the queryDataChangedException
- If optimistic locking is enabled and the record has already been changed/deleted in the database- See Also:
update()
-
delete
int delete() throws DataAccessException, DataChangedException
Deletes this record from the database, based on the value of the primary key or main unique key.Optimistic locking
If a
DELETE
statement is executed andSettings.isExecuteWithOptimisticLocking()
is set totrue
, then this record will first be compared with the latest state in the database. There are two modes of operation for optimistic locking:- With VERSION and/or TIMESTAMP columns configured
This is the preferred way of using optimistic locking in jOOQ. If this is an
UpdatableRecord
and if this record returns fields for eitherTable.getRecordVersion()
orTable.getRecordTimestamp()
, then these values are compared to the corresponding value in the database in theWHERE
clause of the executedDELETE
statement. - Without any specific column configurations
In order to compare this record with the latest state, the database record will be locked pessimistically using a
SELECT .. FOR UPDATE
statement. Not all databases support theFOR UPDATE
clause natively. Namely, the following databases will show slightly different behaviour:-
SQLDialect.CUBRID
andSQLDialect.SQLSERVER
: jOOQ will try to lock the database record using JDBC'sResultSet.TYPE_SCROLL_SENSITIVE
andResultSet.CONCUR_UPDATABLE
. -
SQLDialect.SQLITE
: No pessimistic locking is possible. Client code must assure that no race-conditions can occur between jOOQ's checking of database record state and the actualDELETE
See
SelectQuery.setForUpdate(boolean)
for more details -
Statement examples
The executed statement is
DELETE FROM [table] WHERE [key fields = key values] AND [version/timestamp fields = version/timestamp values]
This is in fact the same as calling
delete(getTable().getPrimaryKey().getFieldsArray())
- Returns:
1
if the record was deleted from the database.0
if deletion was not necessary.- Throws:
DataAccessException
- if something went wrong executing the queryDataChangedException
- If optimistic locking is enabled and the record has already been changed/deleted in the database
- With VERSION and/or TIMESTAMP columns configured
-
refresh
void refresh() throws DataAccessException
Refresh this record from the database.A successful refresh results in the following:
Record.valuesRow()
will have been restored to the respective values from the databaseTableRecord.original()
will match this recordRecord.changed()
will befalse
Refreshing can trigger any of the following actions:
- Executing a new
SELECT
statement, if this is anUpdatableRecord
. - Failing, otherwise
This is the same as calling
record.refresh(record.fields())
- Throws:
DataAccessException
- This exception is thrown if something went wrong executing the refreshSELECT
statementNoDataFoundException
- If the record does not exist anymore in the database
-
refresh
void refresh(Field<?>... fields) throws DataAccessException, NoDataFoundException
Refresh parts of this record from the database.A successful refresh results in the following:
Record.valuesRow()
will have been restored to the respective values from the databaseTableRecord.original()
will match this recordRecord.changed()
will befalse
Refreshing can trigger any of the following actions:
- Executing a new
SELECT
statement, if this is anUpdatableRecord
. - Failing, otherwise
This is the same as calling
record.refresh(record.fields())
- Throws:
DataAccessException
- This exception is thrown if something went wrong executing the refreshSELECT
statementNoDataFoundException
- If the record does not exist anymore in the database
-
refresh
void refresh(Collection<? extends Field<?>> fields) throws DataAccessException, NoDataFoundException
Refresh parts of this record from the database.A successful refresh results in the following:
Record.valuesRow()
will have been restored to the respective values from the databaseTableRecord.original()
will match this recordRecord.changed()
will befalse
Refreshing can trigger any of the following actions:
- Executing a new
SELECT
statement, if this is anUpdatableRecord
. - Failing, otherwise
This is the same as calling
record.refresh(record.fields())
- Throws:
DataAccessException
- This exception is thrown if something went wrong executing the refreshSELECT
statementNoDataFoundException
- If the record does not exist anymore in the database
-
copy
R copy()
Duplicate this record (in memory) and reset all fields from the primary key or main unique key, such that a subsequent call tostore()
will result in anINSERT
statement.- Returns:
- A new record, distinct from
this
record.
-
fetchChild
<O extends TableRecord<O>> O fetchChild(ForeignKey<O,R> key) throws TooManyRowsException, DataAccessException
Fetch a child record of this record, given a foreign key.This returns a child record referencing this record through a given foreign key. If no child record was found, this returns
null
- Throws:
DataAccessException
- if something went wrong executing the queryTooManyRowsException
- if the query returned more than one record- See Also:
ForeignKey.fetchChildren(java.util.Collection)
,ForeignKey.fetchChildren(Record)
,ForeignKey.fetchChildren(Record...)
-
fetchChildren
<O extends TableRecord<O>> Result<O> fetchChildren(ForeignKey<O,R> key) throws DataAccessException
Fetch child records of this record, given a foreign key.This returns childs record referencing this record through a given foreign key.
- Throws:
DataAccessException
- if something went wrong executing the query- See Also:
ForeignKey.fetchChildren(java.util.Collection)
,ForeignKey.fetchChildren(Record)
,ForeignKey.fetchChildren(Record...)
-
-