Module org.jooq
Package org.jooq

Interface UpdatableRecord<R extends UpdatableRecord<R>>

  • 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

    1. it represents a record from a table or view - a TableRecord
    2. 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 an INSERT or an UPDATE statement

    UpdatableRecords are Attachable, which means that they hold an underlying Configuration that they can be detached from. They can also be instantiated without any underlying Configuration, in case of which they have to be attached first, in order to be refreshed, stored, or deleted.

    Author:
    Lukas Eder
    • Method Detail

      • key

        Record key()
        A Record copy holding values for the Table.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 an update() 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 (unless Settings.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 an UPDATE nor an INSERT will be executed.

        Automatic value generation

        Use insert() or update() to explicitly force either statement type.

        • IDENTITY columns

          If there is an IDENTITY column defined on the record's underlying table (see Table.getIdentity()), then the auto-generated IDENTITY value is refreshed automatically on INSERT's. Refreshing is done using Statement.getGeneratedKeys(), where this is supported by the JDBC driver. See also InsertQuery.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 either Table.getRecordVersion() or Table.getRecordTimestamp(), then these values are set onto the INSERT or UPDATE 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 or UPDATE statement manually using the various DSLContext.insertInto(Table), DSLContext.update(Table) methods.

        Optimistic locking

        If an UPDATE statement is executed and Settings.isExecuteWithOptimisticLocking() is set to true, 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 either Table.getRecordVersion() or Table.getRecordTimestamp(), then these values are compared to the corresponding value in the database in the WHERE clause of the executed DELETE 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 the FOR UPDATE clause natively. Namely, the following databases will show slightly different behaviour:

          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 with Record.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 query
        DataChangedException - If optimistic locking is enabled and the record has already been changed/deleted in the database
        See Also:
        insert(), update()
      • insert

        int insert()
            throws DataAccessException
        Store this record back to the database using an INSERT statement.

        This is the same as store(), except that an INSERT 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 with Record.changed(Field, boolean), prior to insertion.

        This is the same as calling record.insert(record.fields())

        Specified by:
        insert in interface TableRecord<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()
      • update

        int update()
            throws DataAccessException,
                   DataChangedException
        Store this record back to the database using an UPDATE statement.

        This is the same as store(), except that an UPDATE 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 with Record.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 query
        DataChangedException - 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 an UPDATE 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 query
        DataChangedException - 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 and Settings.isExecuteWithOptimisticLocking() is set to true, 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 either Table.getRecordVersion() or Table.getRecordTimestamp(), then these values are compared to the corresponding value in the database in the WHERE clause of the executed DELETE 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 the FOR UPDATE clause natively. Namely, the following databases will show slightly different behaviour:

          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 query
        DataChangedException - If optimistic locking is enabled and the record has already been changed/deleted in the database
      • refresh

        void refresh()
              throws DataAccessException
        Refresh this record from the database.

        A successful refresh results in the following:

        Refreshing can trigger any of the following actions:

        • Executing a new SELECT statement, if this is an UpdatableRecord.
        • Failing, otherwise

        This is the same as calling record.refresh(record.fields())

        Throws:
        DataAccessException - This exception is thrown if something went wrong executing the refresh SELECT statement
        NoDataFoundException - 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 to store() will result in an INSERT statement.
        Returns:
        A new record, distinct from this record.