[#1547] Support "optimistic locking" in UpdatableRecord.store() and
delete() - Implemented optimistic locking using a Settings property, rather than an additional API method
This commit is contained in:
parent
6cabc3e762
commit
a737b76efb
@ -61,9 +61,11 @@ import org.jooq.TableRecord;
|
||||
import org.jooq.UDTRecord;
|
||||
import org.jooq.UpdatableRecord;
|
||||
import org.jooq.UpdatableTable;
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.DataChangedException;
|
||||
import org.jooq.exception.InvalidResultException;
|
||||
import org.jooq.impl.Factory;
|
||||
import org.jooq.test.BaseTest;
|
||||
import org.jooq.test.jOOQAbstractTest;
|
||||
|
||||
@ -590,80 +592,82 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, I, IPK, T658,
|
||||
private <R extends UpdatableRecord<R>> void testStoreLocked0(
|
||||
UpdatableTable<R> table, TableField<R, Integer> id, TableField<R, String> string) throws Exception {
|
||||
|
||||
Factory create = create(new Settings().withExecuteWithOptimisticLocking(true));
|
||||
|
||||
// Storing without changing shouldn't execute any queries
|
||||
R record1 = create().fetchOne(table, id.equal(1));
|
||||
assertEquals(0, record1.storeLocked());
|
||||
assertEquals(0, record1.storeLocked());
|
||||
R record1 = create.fetchOne(table, id.equal(1));
|
||||
assertEquals(0, record1.store());
|
||||
assertEquals(0, record1.store());
|
||||
|
||||
// Succeed if there are no concurrency issues
|
||||
record1.setValue(string, "New Title 1");
|
||||
assertEquals(1, record1.storeLocked());
|
||||
assertEquals("New Title 1", create().fetchOne(table, id.equal(1)).getValue(string));
|
||||
assertEquals(1, record1.store());
|
||||
assertEquals("New Title 1", create.fetchOne(table, id.equal(1)).getValue(string));
|
||||
|
||||
// Get new books
|
||||
R record2 = create().fetchOne(table, id.equal(1));
|
||||
R record3 = create().fetchOne(table, id.equal(1));
|
||||
R record2 = create.fetchOne(table, id.equal(1));
|
||||
R record3 = create.fetchOne(table, id.equal(1));
|
||||
|
||||
// Still won't fail, but this will cause record3 to be stale
|
||||
record2.setValue(string, "New Title 2");
|
||||
assertEquals(1, record2.storeLocked());
|
||||
assertEquals("New Title 2", create().fetchOne(table, id.equal(1)).getValue(string));
|
||||
assertEquals(1, record2.store());
|
||||
assertEquals("New Title 2", create.fetchOne(table, id.equal(1)).getValue(string));
|
||||
|
||||
// Storing without changing shouldn't execute any queries
|
||||
assertEquals(0, record3.storeLocked());
|
||||
assertEquals(0, record3.store());
|
||||
|
||||
// This should fail as record3 is stale
|
||||
record3.setValue(string, "New Title 3");
|
||||
try {
|
||||
record3.storeLocked();
|
||||
record3.store();
|
||||
fail();
|
||||
}
|
||||
catch (DataChangedException expected) {}
|
||||
assertEquals("New Title 2", create().fetchOne(table, id.equal(1)).getValue(string));
|
||||
assertEquals("New Title 2", create.fetchOne(table, id.equal(1)).getValue(string));
|
||||
|
||||
// Refreshing first will work, though
|
||||
record3.refresh();
|
||||
record3.setValue(string, "New Title 3");
|
||||
assertEquals(1, record3.storeLocked());
|
||||
assertEquals("New Title 3", create().fetchOne(table, id.equal(1)).getValue(string));
|
||||
assertEquals(1, record3.store());
|
||||
assertEquals("New Title 3", create.fetchOne(table, id.equal(1)).getValue(string));
|
||||
|
||||
// Get new books
|
||||
R record4 = create().fetchOne(table, id.equal(1));
|
||||
R record5 = create().fetchOne(table, id.equal(1));
|
||||
R record4 = create.fetchOne(table, id.equal(1));
|
||||
R record5 = create.fetchOne(table, id.equal(1));
|
||||
|
||||
// Delete the book
|
||||
assertEquals(1, record4.deleteLocked());
|
||||
assertEquals(1, record4.delete());
|
||||
|
||||
// Storing without changing shouldn't execute any queries
|
||||
assertEquals(0, record5.storeLocked());
|
||||
assertEquals(0, record5.store());
|
||||
|
||||
// This should fail, as the database record no longer exists
|
||||
record5.setValue(string, "New Title 5");
|
||||
try {
|
||||
record5.storeLocked();
|
||||
record5.store();
|
||||
fail();
|
||||
}
|
||||
catch (DataChangedException expected) {}
|
||||
|
||||
// Restore the book, then it should work
|
||||
assertEquals(1, record4.storeLocked());
|
||||
assertEquals(1, record5.storeLocked());
|
||||
assertEquals("New Title 5", create().fetchOne(table, id.equal(1)).getValue(string));
|
||||
assertEquals(1, record4.store());
|
||||
assertEquals(1, record5.store());
|
||||
assertEquals("New Title 5", create.fetchOne(table, id.equal(1)).getValue(string));
|
||||
|
||||
// Deleting the original should no longer be possible
|
||||
try {
|
||||
record4.deleteLocked();
|
||||
record4.delete();
|
||||
fail();
|
||||
}
|
||||
catch (DataChangedException expected) {}
|
||||
|
||||
// Refreshing and deleting should work
|
||||
record4.refresh();
|
||||
assertEquals(1, record4.deleteLocked());
|
||||
assertEquals(1, record4.delete());
|
||||
|
||||
// Now the other record cannot be deleted anymore
|
||||
try {
|
||||
record5.deleteLocked();
|
||||
record5.delete();
|
||||
fail();
|
||||
}
|
||||
catch (DataChangedException expected) {}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<artifactId>jooq-parent</artifactId>
|
||||
<version>2.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
|
||||
<groupId>org.jooq</groupId>
|
||||
<artifactId>jooq</artifactId>
|
||||
<name>jOOQ</name>
|
||||
@ -38,7 +38,7 @@
|
||||
<strict>false</strict>
|
||||
<schemaDirectory>src/main/resources/xsd</schemaDirectory>
|
||||
<schemaIncludes>
|
||||
<include>jooq-runtime-2.3.0.xsd</include>
|
||||
<include>jooq-runtime-2.5.0.xsd</include>
|
||||
</schemaIncludes>
|
||||
<generatePackage>org.jooq.conf</generatePackage>
|
||||
<args>
|
||||
|
||||
@ -38,6 +38,7 @@ package org.jooq;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.DataChangedException;
|
||||
|
||||
@ -71,6 +72,25 @@ public interface TableRecord<R extends TableRecord<R>> extends Record {
|
||||
* record.</li>
|
||||
* <li>If this record was loaded by jOOQ, and the provided keys' value was
|
||||
* not changed, an <code>UPDATE</code> statement is executed.</li>
|
||||
* <li>If an <code>UPDATE</code> statement is executed and
|
||||
* {@link Settings#isExecuteWithOptimisticLocking()} is set to
|
||||
* <code>true</code>, then this record will first be compared with the
|
||||
* latest state in the database. In order to compare this record with the
|
||||
* latest state, the database record will be locked pessimistically using a
|
||||
* <code>SELECT .. FOR UPDATE</code> statement. Not all databases support
|
||||
* the <code>FOR UPDATE</code> clause natively. Namely, the following
|
||||
* databases will show slightly different behaviour:
|
||||
* <ul>
|
||||
* <li> {@link SQLDialect#CUBRID} and {@link SQLDialect#SQLSERVER}: jOOQ will
|
||||
* try to lock the database record using JDBC's
|
||||
* {@link ResultSet#TYPE_SCROLL_SENSITIVE} and
|
||||
* {@link ResultSet#CONCUR_UPDATABLE}.</li>
|
||||
* <li> {@link 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 actual <code>UPDATE</code></li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* See {@link LockProvider#setForUpdate(boolean)} for more details</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* In either statement, only those fields are inserted/updated, which had
|
||||
@ -106,49 +126,10 @@ public interface TableRecord<R extends TableRecord<R>> extends Record {
|
||||
* <code>WHERE</code> clause.
|
||||
* @return The number of stored records.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws DataChangedException If optimistic locking is enabled and the
|
||||
* record has already been changed/deleted in the database
|
||||
*/
|
||||
int storeUsing(TableField<R, ?>... keys) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Store this record back to the database assuming an optimistic lock.
|
||||
* <p>
|
||||
* This performs the same action as {@link #storeUsing(TableField...)},
|
||||
* except that if an <code>UPDATE</code> is performed, this record will
|
||||
* first be compared with the latest state in the database.
|
||||
* <p>
|
||||
* Note that in order to compare this record with the latest state, the
|
||||
* database record will be locked pessimistically using a
|
||||
* <code>SELECT .. FOR UPDATE</code> statement. Not all databases support
|
||||
* the <code>FOR UPDATE</code> clause natively. Namely, the following
|
||||
* databases will show slightly different behaviour:
|
||||
* <ul>
|
||||
* <li> {@link SQLDialect#CUBRID} and {@link SQLDialect#SQLSERVER}: jOOQ will
|
||||
* try to lock the database record using JDBC's
|
||||
* {@link ResultSet#TYPE_SCROLL_SENSITIVE} and
|
||||
* {@link ResultSet#CONCUR_UPDATABLE}.</li>
|
||||
* <li> {@link 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 actual <code>UPDATE</code></li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* See {@link LockProvider#setForUpdate(boolean)} for more details
|
||||
* <p>
|
||||
* Unlike {@link #storeUsing(TableField...)}, this will fail if several
|
||||
* records are concerned.
|
||||
*
|
||||
* @param keys The key fields used for deciding whether to execute an
|
||||
* <code>INSERT</code> or <code>UPDATE</code> statement. If an
|
||||
* <code>UPDATE</code> statement is executed, they are also the
|
||||
* key fields for the <code>UPDATE</code> statement's
|
||||
* <code>WHERE</code> clause.
|
||||
* @return The number of stored records.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws DataChangedException if the record has already been changed in
|
||||
* the database
|
||||
* @see #storeUsing(TableField...)
|
||||
* @see LockProvider#setForUpdate(boolean)
|
||||
*/
|
||||
int storeLockedUsing(TableField<R, ?>... keys) throws DataAccessException, DataChangedException;
|
||||
int storeUsing(TableField<R, ?>... keys) throws DataAccessException, DataChangedException;
|
||||
|
||||
/**
|
||||
* Deletes this record from the database, based on the value of the provided
|
||||
@ -157,23 +138,11 @@ public interface TableRecord<R extends TableRecord<R>> extends Record {
|
||||
* The executed statement is <code><pre>
|
||||
* DELETE FROM [table]
|
||||
* WHERE [key fields = key values]</pre></code>
|
||||
*
|
||||
* @param keys The key fields for the <code>DELETE</code> statement's
|
||||
* <code>WHERE</code> clause.
|
||||
* @return The number of deleted records.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
*/
|
||||
int deleteUsing(TableField<R, ?>... keys) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Deletes this record from the database assuming an optimistic lock.
|
||||
* <p>
|
||||
* This performs the same action as {@link #deleteUsing(TableField...)},
|
||||
* except that this record will first be compared with the latest state in
|
||||
* the database.
|
||||
* <p>
|
||||
* Note that in order to compare this record with the latest state, the
|
||||
* database record will be locked pessimistically using a
|
||||
* If {@link Settings#isExecuteWithOptimisticLocking()} is set to
|
||||
* <code>true</code>, then this record will first be compared with the
|
||||
* latest state in the database. In order to compare this record with the
|
||||
* latest state, the database record will be locked pessimistically using a
|
||||
* <code>SELECT .. FOR UPDATE</code> statement. Not all databases support
|
||||
* the <code>FOR UPDATE</code> clause natively. Namely, the following
|
||||
* databases will show slightly different behaviour:
|
||||
@ -188,20 +157,15 @@ public interface TableRecord<R extends TableRecord<R>> extends Record {
|
||||
* </ul>
|
||||
* <p>
|
||||
* See {@link LockProvider#setForUpdate(boolean)} for more details
|
||||
* <p>
|
||||
* Unlike {@link #deleteUsing(TableField...)}, this will fail if several
|
||||
* records are concerned.
|
||||
*
|
||||
* @param keys The key fields for the <code>DELETE</code> statement's
|
||||
* <code>WHERE</code> clause.
|
||||
* @return The number of deleted records.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws DataChangedException if the record has already been changed in
|
||||
* the database
|
||||
* @see #deleteUsing(TableField...)
|
||||
* @see LockProvider#setForUpdate(boolean)
|
||||
* @throws DataChangedException If optimistic locking is enabled and the
|
||||
* record has already been changed/deleted in the database
|
||||
*/
|
||||
int deleteLockedUsing(TableField<R, ?>... keys) throws DataAccessException, DataChangedException;
|
||||
int deleteUsing(TableField<R, ?>... keys) throws DataAccessException, DataChangedException;
|
||||
|
||||
/**
|
||||
* Refresh this record from the database, based on the value of the provided
|
||||
|
||||
@ -38,6 +38,7 @@ package org.jooq;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.jooq.conf.Settings;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.DataChangedException;
|
||||
|
||||
@ -97,13 +98,33 @@ public interface UpdatableRecord<R extends UpdatableRecord<R>> extends Updatable
|
||||
* record.</li>
|
||||
* <li>If this record was loaded by jOOQ, and the primary key value was not
|
||||
* changed, an <code>UPDATE</code> statement is executed.</li>
|
||||
* <li>If an <code>UPDATE</code> statement is executed and
|
||||
* {@link Settings#isExecuteWithOptimisticLocking()} is set to
|
||||
* <code>true</code>, then this record will first be compared with the
|
||||
* latest state in the database. In order to compare this record with the
|
||||
* latest state, the database record will be locked pessimistically using a
|
||||
* <code>SELECT .. FOR UPDATE</code> statement. Not all databases support
|
||||
* the <code>FOR UPDATE</code> clause natively. Namely, the following
|
||||
* databases will show slightly different behaviour:
|
||||
* <ul>
|
||||
* <li> {@link SQLDialect#CUBRID} and {@link SQLDialect#SQLSERVER}: jOOQ will
|
||||
* try to lock the database record using JDBC's
|
||||
* {@link ResultSet#TYPE_SCROLL_SENSITIVE} and
|
||||
* {@link ResultSet#CONCUR_UPDATABLE}.</li>
|
||||
* <li> {@link 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 actual <code>UPDATE</code></li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* In either statement, only those fields are inserted/updated, which had
|
||||
* been explicitly set by client code, in order to allow for
|
||||
* <code>DEFAULT</code> values to be applied by the underlying RDBMS. If no
|
||||
* fields were modified, neither an <code>UPDATE</code> nor an
|
||||
* <code>INSERT</code> will be executed. Possible statements are
|
||||
* See {@link LockProvider#setForUpdate(boolean)} for more details</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* In either <code>INSERT</code> or <code>UPDATE</code> statement, only
|
||||
* those fields are inserted/updated, which had been explicitly set by
|
||||
* client code, in order to allow for <code>DEFAULT</code> values to be
|
||||
* applied by the underlying RDBMS. If no fields were modified, neither an
|
||||
* <code>UPDATE</code> nor an <code>INSERT</code> will be executed. Possible
|
||||
* statements are
|
||||
* <ul>
|
||||
* <li>
|
||||
* <code><pre>
|
||||
@ -132,44 +153,11 @@ public interface UpdatableRecord<R extends UpdatableRecord<R>> extends Updatable
|
||||
* @return <code>1</code> if the record was stored to the database. <code>0
|
||||
* </code> if storing was not necessary.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws DataChangedException If optimistic locking is enabled and the
|
||||
* record has already been changed/deleted in the database
|
||||
* @see #storeUsing(TableField...)
|
||||
*/
|
||||
int store() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Store this record back to the database assuming an optimistic lock.
|
||||
* <p>
|
||||
* This performs the same action as {@link #store()}, except that if an
|
||||
* <code>UPDATE</code> is performed, this record will first be compared with
|
||||
* the latest state in the database.
|
||||
* <p>
|
||||
* Note that in order to compare this record with the latest state, the
|
||||
* database record will be locked pessimistically using a
|
||||
* <code>SELECT .. FOR UPDATE</code> statement. Not all databases support
|
||||
* the <code>FOR UPDATE</code> clause natively. Namely, the following
|
||||
* databases will show slightly different behaviour:
|
||||
* <ul>
|
||||
* <li> {@link SQLDialect#CUBRID} and {@link SQLDialect#SQLSERVER}: jOOQ will
|
||||
* try to lock the database record using JDBC's
|
||||
* {@link ResultSet#TYPE_SCROLL_SENSITIVE} and
|
||||
* {@link ResultSet#CONCUR_UPDATABLE}.</li>
|
||||
* <li> {@link 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 actual <code>UPDATE</code></li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* See {@link LockProvider#setForUpdate(boolean)} for more details
|
||||
*
|
||||
* @return <code>1</code> if the record was stored to the database. <code>0
|
||||
* </code> if storing was not necessary.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws DataChangedException if the record has already been
|
||||
* changed/deleted in the database
|
||||
* @see #store()
|
||||
* @see #storeLockedUsing(TableField...)
|
||||
* @see LockProvider#setForUpdate(boolean)
|
||||
*/
|
||||
int storeLocked() throws DataAccessException, DataChangedException;
|
||||
int store() throws DataAccessException, DataChangedException;
|
||||
|
||||
/**
|
||||
* Deletes this record from the database, based on the value of the primary
|
||||
@ -179,24 +167,10 @@ public interface UpdatableRecord<R extends UpdatableRecord<R>> extends Updatable
|
||||
* DELETE FROM [table]
|
||||
* WHERE [main key fields = main key values]</pre></code>
|
||||
* <p>
|
||||
* This is in fact the same as calling
|
||||
* <code>delete(getTable().getMainKey().getFieldsArray())</code>
|
||||
*
|
||||
* @return <code>1</code> if the record was deleted from the database.
|
||||
* <code>0</code> if deletion was not necessary.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @see #deleteUsing(TableField...)
|
||||
*/
|
||||
int delete() throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Deletes this record from the database assuming an optimistic lock.
|
||||
* <p>
|
||||
* This performs the same action as {@link #delete()}, except that this
|
||||
* record will first be compared with the latest state in the database.
|
||||
* <p>
|
||||
* Note that in order to compare this record with the latest state, the
|
||||
* database record will be locked pessimistically using a
|
||||
* If {@link Settings#isExecuteWithOptimisticLocking()} is set to
|
||||
* <code>true</code>, then this record will first be compared with the
|
||||
* latest state in the database. In order to compare this record with the
|
||||
* latest state, the database record will be locked pessimistically using a
|
||||
* <code>SELECT .. FOR UPDATE</code> statement. Not all databases support
|
||||
* the <code>FOR UPDATE</code> clause natively. Namely, the following
|
||||
* databases will show slightly different behaviour:
|
||||
@ -211,17 +185,18 @@ public interface UpdatableRecord<R extends UpdatableRecord<R>> extends Updatable
|
||||
* </ul>
|
||||
* <p>
|
||||
* See {@link LockProvider#setForUpdate(boolean)} for more details
|
||||
* <p>
|
||||
* This is in fact the same as calling
|
||||
* <code>delete(getTable().getMainKey().getFieldsArray())</code>
|
||||
*
|
||||
* @return <code>1</code> if the record was deleted from the database.
|
||||
* <code>0</code> if deletion was not necessary.
|
||||
* @throws DataAccessException if something went wrong executing the query
|
||||
* @throws DataChangedException if the record has already been
|
||||
* changed/deleted in the database
|
||||
* @see #delete()
|
||||
* @throws DataChangedException If optimistic locking is enabled and the
|
||||
* record has already been changed/deleted in the database
|
||||
* @see #deleteUsing(TableField...)
|
||||
* @see LockProvider#setForUpdate(boolean)
|
||||
*/
|
||||
int deleteLocked() throws DataAccessException, DataChangedException;
|
||||
int delete() throws DataAccessException, DataChangedException;
|
||||
|
||||
/**
|
||||
* Refresh this record from the database, based on the value of the primary
|
||||
|
||||
@ -42,6 +42,7 @@ import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
import org.jooq.ConditionProvider;
|
||||
import org.jooq.Configuration;
|
||||
import org.jooq.DeleteQuery;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.Identity;
|
||||
@ -95,15 +96,7 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractRecord im
|
||||
|
||||
@Override
|
||||
public final int storeUsing(TableField<R, ?>... keys) {
|
||||
return storeUsing0(keys, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int storeLockedUsing(TableField<R, ?>... keys) {
|
||||
return storeUsing0(keys, true);
|
||||
}
|
||||
|
||||
private final int storeUsing0(TableField<R, ?>[] keys, boolean checkIfChanged) {
|
||||
boolean checkIfChanged = isExecuteWithOptimisticLocking();
|
||||
boolean executeUpdate = false;
|
||||
|
||||
for (TableField<R, ?> field : keys) {
|
||||
@ -133,6 +126,16 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractRecord im
|
||||
return result;
|
||||
}
|
||||
|
||||
private final boolean isExecuteWithOptimisticLocking() {
|
||||
Configuration configuration = getConfiguration();
|
||||
|
||||
if (configuration != null) {
|
||||
return TRUE.equals(configuration.getSettings().isExecuteWithOptimisticLocking());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private final int storeInsert() {
|
||||
Factory create = create();
|
||||
@ -239,15 +242,8 @@ public class TableRecordImpl<R extends TableRecord<R>> extends AbstractRecord im
|
||||
|
||||
@Override
|
||||
public final int deleteUsing(TableField<R, ?>... keys) {
|
||||
return deleteUsing0(keys, false);
|
||||
}
|
||||
boolean checkIfChanged = isExecuteWithOptimisticLocking();
|
||||
|
||||
@Override
|
||||
public final int deleteLockedUsing(TableField<R, ?>... keys) {
|
||||
return deleteUsing0(keys, true);
|
||||
}
|
||||
|
||||
private int deleteUsing0(TableField<R, ?>[] keys, boolean checkIfChanged) {
|
||||
try {
|
||||
DeleteQuery<R> delete = create().deleteQuery(getTable());
|
||||
|
||||
|
||||
@ -76,21 +76,11 @@ public class UpdatableRecordImpl<R extends UpdatableRecord<R>> extends TableReco
|
||||
return storeUsing(getMainKey().getFieldsArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int storeLocked() {
|
||||
return storeLockedUsing(getMainKey().getFieldsArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int delete() {
|
||||
return deleteUsing(getMainKey().getFieldsArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int deleteLocked() {
|
||||
return deleteLockedUsing(getMainKey().getFieldsArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void refresh() {
|
||||
refreshUsing(getMainKey().getFieldsArray());
|
||||
|
||||
168
jOOQ/src/main/resources/xsd/jooq-runtime-2.5.0.xsd
Normal file
168
jOOQ/src/main/resources/xsd/jooq-runtime-2.5.0.xsd
Normal file
@ -0,0 +1,168 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<schema
|
||||
xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:jooq-runtime="http://www.jooq.org/xsd/jooq-runtime-2.3.0.xsd"
|
||||
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
|
||||
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
|
||||
jaxb:version="1.0" jaxb:extensionBindingPrefixes="xjc"
|
||||
targetNamespace="http://www.jooq.org/xsd/jooq-runtime-2.3.0.xsd">
|
||||
|
||||
<annotation>
|
||||
<appinfo>
|
||||
<jaxb:globalBindings>
|
||||
<xjc:serializable uid="205"/>
|
||||
</jaxb:globalBindings>
|
||||
</appinfo>
|
||||
</annotation>
|
||||
|
||||
<element name="settings" type="jooq-runtime:Settings"/>
|
||||
|
||||
<complexType name="Settings">
|
||||
<all>
|
||||
<!-- Whether any schema name should be rendered at all.
|
||||
Use this for single-schema environments, or when all objects are made
|
||||
available using synonyms -->
|
||||
<element name="renderSchema" type="boolean" minOccurs="0" maxOccurs="1" default="true"/>
|
||||
|
||||
<!-- Configure render mapping for runtime schema / table rewriting in
|
||||
generated SQL -->
|
||||
<element name="renderMapping" type="jooq-runtime:RenderMapping" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<!-- Whether rendered schema, table, column names, etc should be quoted
|
||||
in rendered SQL, or transformed in any other way.
|
||||
This is set to "QUOTED" by default for backwards-compatibility -->
|
||||
<element name="renderNameStyle" type="jooq-runtime:RenderNameStyle" minOccurs="0" maxOccurs="1" default="QUOTED"/>
|
||||
|
||||
<!-- Whether SQL keywords should be rendered with upper or lower case -->
|
||||
<element name="renderKeywordStyle" type="jooq-runtime:RenderKeywordStyle" minOccurs="0" maxOccurs="1" default="LOWER"/>
|
||||
|
||||
<!-- Whether rendered SQL should be pretty-printed -->
|
||||
<element name="renderFormatted" type="boolean" minOccurs="0" maxOccurs="1" default="false"/>
|
||||
|
||||
<!-- The type of statement that is to be executed -->
|
||||
<element name="statementType" type="jooq-runtime:StatementType" minOccurs="0" maxOccurs="1" default="PREPARED_STATEMENT"/>
|
||||
|
||||
<!-- When set to true, this will add jOOQ's default logging ExecuteListeners -->
|
||||
<element name="executeLogging" type="boolean" minOccurs="0" maxOccurs="1" default="true"/>
|
||||
|
||||
<!-- The event listeners to be notified upon execution events -->
|
||||
<element name="executeListeners" type="jooq-runtime:ExecuteListeners" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<!-- Whether store() and delete() methods should be executed with optimistic locking -->
|
||||
<element name="executeWithOptimisticLocking" type="boolean" minOccurs="0" maxOccurs="1" default="false"/>
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
<complexType name="RenderMapping">
|
||||
<all>
|
||||
<!-- The default schema as defined in org.jooq.Schema.getName()
|
||||
This schema will be omitted in rendered SQL -->
|
||||
<element name="defaultSchema" type="string" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<!-- The mapped schemata configuration -->
|
||||
<element name="schemata" type="jooq-runtime:MappedSchemata" minOccurs="0" maxOccurs="1"/>
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
<complexType name="MappedSchemata">
|
||||
<sequence>
|
||||
<element name="schema" type="jooq-runtime:MappedSchema" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="MappedSchema">
|
||||
<all>
|
||||
<!-- The input schema as defined in org.jooq.Schema.getName() -->
|
||||
<element name="input" type="string" minOccurs="1" maxOccurs="1"/>
|
||||
|
||||
<!-- The output schema as it will be rendered in SQL
|
||||
When this is omitted, you can still apply table mapping -->
|
||||
<element name="output" type="string" minOccurs="0" maxOccurs="1"/>
|
||||
|
||||
<!-- Configure table mapping for runtime table rewriting in
|
||||
generated SQL -->
|
||||
<element name="tables" type="jooq-runtime:MappedTables" minOccurs="0" maxOccurs="1"/>
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
<complexType name="MappedTables">
|
||||
<sequence>
|
||||
<element name="table" type="jooq-runtime:MappedTable" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="MappedTable">
|
||||
<all>
|
||||
<!-- The input schema as defined in org.jooq.Table.getName() -->
|
||||
<element name="input" type="string" minOccurs="1" maxOccurs="1"/>
|
||||
|
||||
<!-- The output schema as it will be rendered in SQL -->
|
||||
<element name="output" type="string" minOccurs="1" maxOccurs="1"/>
|
||||
</all>
|
||||
</complexType>
|
||||
|
||||
<simpleType name="StatementType">
|
||||
<restriction base="string">
|
||||
|
||||
<!-- Execute statements with inlined bind values, avoiding JDBC's
|
||||
PreparedStatements -->
|
||||
<enumeration value="STATIC_STATEMENT"/>
|
||||
|
||||
<!-- Execute statements with bind values, using JDBC's
|
||||
PreparedStatements -->
|
||||
<enumeration value="PREPARED_STATEMENT"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="RenderNameStyle">
|
||||
<restriction base="string">
|
||||
|
||||
<!-- Render object names quoted, as defined in the database. Use this
|
||||
to stay on the safe side with case-sensitivity and special
|
||||
characters. For instance:
|
||||
Oracle : "SYS"."ALL_TAB_COLS"
|
||||
MySQL : `information_schema`.`TABLES`
|
||||
SQL Server: [INFORMATION_SCHEMA].[TABLES] -->
|
||||
<enumeration value="QUOTED"/>
|
||||
|
||||
<!-- Render object names, as defined in the database. For instance:
|
||||
Oracle : SYS.ALL_TAB_COLS
|
||||
MySQL : information_schema.TABLES
|
||||
SQL Server: INFORMATION_SCHEMA.TABLES -->
|
||||
<enumeration value="AS_IS"/>
|
||||
|
||||
<!-- Force rendering object names in lower case. For instance:
|
||||
Oracle : sys.all_tab_cols
|
||||
MySQL : information_schema.tables
|
||||
SQL Server: information_schema.tables -->
|
||||
<enumeration value="LOWER"/>
|
||||
|
||||
<!-- Force rendering object names in upper case. For instance:
|
||||
Oracle : SYS.ALL_TAB_COLS
|
||||
MySQL : INFORMATION_SCHEMA.TABLES
|
||||
SQL Server: INFORMATION_SCHEMA.TABLES -->
|
||||
<enumeration value="UPPER"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<simpleType name="RenderKeywordStyle">
|
||||
<restriction base="string">
|
||||
|
||||
<!-- Keywords are rendered in lower case. For instance:
|
||||
select .. from .. where .. -->
|
||||
<enumeration value="LOWER"/>
|
||||
|
||||
<!-- Keywords are rendered in upper case. For instance:
|
||||
SELECT .. FROM .. WHERE .. -->
|
||||
<enumeration value="UPPER"/>
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<complexType name="ExecuteListeners">
|
||||
<sequence>
|
||||
|
||||
<!-- An event listener implementing org.jooq.ExecuteListener -->
|
||||
<element name="executeListener" type="string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</schema>
|
||||
Loading…
Reference in New Issue
Block a user