[#2265] Add Result.store(), delete(), refresh(), to allow for
batch-synchronisation of Records contained in a Result - Prototype implementation
This commit is contained in:
parent
342c769309
commit
712a0f2f62
@ -52,6 +52,7 @@ import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.jooq.Cursor;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.Record2;
|
||||
import org.jooq.Record3;
|
||||
@ -134,23 +135,32 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
return;
|
||||
}
|
||||
|
||||
Result<B> b2 = create().selectFrom(TBook()).keepResultSet(KEEP_AFTER_FETCH).fetch();
|
||||
Result<Record> b2 = create().select().from(TBook().getName()).keepResultSet(KEEP_AFTER_FETCH).fetch();
|
||||
Record r = b2.get(0);
|
||||
assertNotNull(b2.resultSet());
|
||||
assertNotNull(r.resultSet());
|
||||
testFailUpdateRow(b2.resultSet());
|
||||
|
||||
// Changing a TITLE has no effect
|
||||
b2.get(0).setValue(TBook_TITLE(), "XX");
|
||||
assertTrue(b2.get(0).changed());
|
||||
assertFalse(b2.get(0).original().equals(b2.get(0)));
|
||||
r.setValue(TBook_TITLE(), "XX");
|
||||
assertEquals("XX", r.getValue(TBook_TITLE()));
|
||||
assertTrue(r.changed());
|
||||
assertFalse(r.original().equals(r));
|
||||
assertEquals(BOOK_TITLES.get(0), getBook(1).getValue(TBook_TITLE()));
|
||||
|
||||
// Refresh the record
|
||||
r.refresh();
|
||||
assertEquals("1984", r.getValue(TBook_TITLE()));
|
||||
assertFalse(r.changed());
|
||||
assertEquals(r.original(), r);
|
||||
|
||||
b2.close();
|
||||
assertNull(b2.resultSet());
|
||||
|
||||
Cursor<B> c1 = create().selectFrom(TBook()).keepResultSet(KEEP_AFTER_FETCH).fetchLazy();
|
||||
Cursor<Record> c1 = create().select().from(TBook().getName()).keepResultSet(KEEP_AFTER_FETCH).fetchLazy();
|
||||
assertFalse(c1.closesAfterFetch());
|
||||
while (c1.hasNext()) {
|
||||
Result<B> result = c1.fetch(1);
|
||||
Result<Record> result = c1.fetch(1);
|
||||
assertNotNull(result.get(0).resultSet());
|
||||
assertNotNull(result.resultSet());
|
||||
assertNotNull(c1.resultSet());
|
||||
@ -304,5 +314,6 @@ extends BaseTest<A, AP, B, S, B2S, BS, L, X, DATE, BOOL, D, T, U, UU, I, IPK, T7
|
||||
* - Implement all data types from ResultSet.updateXXX() (e.g. updateInt(), etc)
|
||||
* - Implement UPDATE_ON_STORE
|
||||
* - refresh() should not execute a new query if a ResultSet is available
|
||||
* - TYPE_SCROLL_SENSITIVE should be active for KEEP_AFTER_FETCH (for refresh())
|
||||
*/
|
||||
}
|
||||
|
||||
@ -1042,6 +1042,57 @@ public interface Record extends Attachable, Comparable<Record> {
|
||||
// Methods related to the underlying ResultSet (if applicable)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Refresh this record from the database.
|
||||
* <p>
|
||||
* A successful refresh results in the following:
|
||||
* <ul>
|
||||
* <li>{@link #valuesRow()} will have been restored to the respective values
|
||||
* from the database</li>
|
||||
* <li>{@link #original()} will match this record</li>
|
||||
* <li>{@link #changed()} will be <code>false</code></li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* Refreshing can trigger any of the following actions:
|
||||
* <ul>
|
||||
* <li>Re-reading the underlying {@link #resultSet()}, if that
|
||||
* <code>ResultSet</code> is available.</li>
|
||||
* <li>Executing a new <code>SELECT</code> statement, if this is an
|
||||
* {@link UpdatableRecord}.</li>
|
||||
* <li>Failing, otherwise</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This is the same as calling <code>record.refresh(record.fields())</code>
|
||||
*
|
||||
* @throws DataAccessException This exception is thrown if
|
||||
* <ul>
|
||||
* <li>something went wrong executing the query</li> <li>the
|
||||
* {@link #resultSet()} is not available, or is in
|
||||
* {@link ResultSet#TYPE_FORWARD_ONLY} mode, such that
|
||||
* refreshing is not possible.</li><li>the record does not exist
|
||||
* anymore in the database</li>
|
||||
* </ul>
|
||||
* @see UpdatableRecord#refresh()
|
||||
* @see ResultQuery#keepResultSet(KeepResultSetMode)
|
||||
*/
|
||||
void refresh() throws DataAccessException;
|
||||
|
||||
// /**
|
||||
// * Refresh this record from the database, based on the value of the primary
|
||||
// * key or main unique key.
|
||||
// * <p>
|
||||
// * The executed statement is <code><pre>
|
||||
// * SELECT [fields] FROM [table]
|
||||
// * WHERE [primary key fields = primary key values]</pre></code>
|
||||
// *
|
||||
// * @throws DataAccessException This exception is thrown if
|
||||
// * <ul>
|
||||
// * <li>something went wrong executing the query</li> <li>the
|
||||
// * record does not exist anymore in the database</li>
|
||||
// * </ul>
|
||||
// */
|
||||
// void refresh(Field<?>... fields) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Close the underlying JDBC {@link ResultSet}, if applicable.
|
||||
* <p>
|
||||
|
||||
@ -317,6 +317,7 @@ public interface UpdatableRecord<R extends UpdatableRecord<R>> extends TableReco
|
||||
* record does not exist anymore in the database</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
void refresh() throws DataAccessException;
|
||||
|
||||
/**
|
||||
|
||||
@ -63,6 +63,7 @@ import org.jooq.RecordMapper;
|
||||
import org.jooq.Result;
|
||||
import org.jooq.Table;
|
||||
import org.jooq.UniqueKey;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.exception.InvalidResultException;
|
||||
import org.jooq.exception.MappingException;
|
||||
import org.jooq.tools.Convert;
|
||||
@ -692,6 +693,29 @@ abstract class AbstractRecord extends AbstractStore implements Record {
|
||||
// XXX: Methods related to the underlying ResultSet (if applicable)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Override
|
||||
public void refresh() {
|
||||
if (rs != null) {
|
||||
try {
|
||||
|
||||
// [#2265] TODO: This code is prototypical. fetchLazy() is not
|
||||
// the best way to fetch a record
|
||||
rs.absolute(rsIndex - 1);
|
||||
Record record = create().fetchLazy(rs).fetchOne();
|
||||
|
||||
for (int i = 0; i < record.size(); i++) {
|
||||
setValue(i, new Value<Object>(record.getValue(i)));
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw translate("Cannot refresh record", e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new DataAccessException("Cannot refresh record. No ResultSet available");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void close() {
|
||||
try {
|
||||
|
||||
@ -35,11 +35,13 @@
|
||||
*/
|
||||
package org.jooq.impl;
|
||||
|
||||
import static java.sql.ResultSet.CONCUR_READ_ONLY;
|
||||
import static java.sql.ResultSet.CONCUR_UPDATABLE;
|
||||
import static java.sql.ResultSet.TYPE_SCROLL_SENSITIVE;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.concurrent.Executors.newSingleThreadExecutor;
|
||||
import static org.jooq.KeepResultSetMode.CLOSE_AFTER_FETCH;
|
||||
import static org.jooq.KeepResultSetMode.KEEP_AFTER_FETCH;
|
||||
import static org.jooq.KeepResultSetMode.UPDATE_ON_CHANGE;
|
||||
import static org.jooq.KeepResultSetMode.UPDATE_ON_STORE;
|
||||
import static org.jooq.SQLDialect.ASE;
|
||||
@ -224,7 +226,12 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
}
|
||||
}
|
||||
|
||||
// [#1846] When updatable Results are fetched
|
||||
// [#1846] When scrollable Results are fetched
|
||||
else if (keepResultSetMode == KEEP_AFTER_FETCH) {
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql(), TYPE_SCROLL_SENSITIVE, CONCUR_READ_ONLY));
|
||||
}
|
||||
|
||||
// [#1846] When scrollable and updatable Results are fetched
|
||||
else if (keepResultSetMode == UPDATE_ON_CHANGE ||
|
||||
keepResultSetMode == UPDATE_ON_STORE) {
|
||||
ctx.statement(ctx.connection().prepareStatement(ctx.sql(), TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE));
|
||||
@ -350,6 +357,7 @@ abstract class AbstractResultQuery<R extends Record> extends AbstractQuery imple
|
||||
@Override
|
||||
protected final boolean keepResultSet() {
|
||||
return lazy
|
||||
|| keepResultSetMode == KEEP_AFTER_FETCH
|
||||
|| keepResultSetMode == UPDATE_ON_CHANGE
|
||||
|| keepResultSetMode == UPDATE_ON_STORE;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user