mirror of https://github.com/apache/openjpa.git
Non-optimistic transactions will no longer perform a version check when committing dirty objects, unless the NonOptimisticVersionCheck compatibility property is set to true. This allows dirty instances enlisted in a non-optimistic transaction to be allowed to overwrite conflicting versions in the database.
git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@446799 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
a7cfbfc4c9
commit
944f8ad22c
|
@ -35,6 +35,7 @@ import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||||
import org.apache.openjpa.kernel.PCState;
|
import org.apache.openjpa.kernel.PCState;
|
||||||
import org.apache.openjpa.lib.conf.Configurable;
|
import org.apache.openjpa.lib.conf.Configurable;
|
||||||
import org.apache.openjpa.lib.conf.Configuration;
|
import org.apache.openjpa.lib.conf.Configuration;
|
||||||
|
import org.apache.openjpa.util.ImplHelper;
|
||||||
import org.apache.openjpa.util.OpenJPAException;
|
import org.apache.openjpa.util.OpenJPAException;
|
||||||
import org.apache.openjpa.util.OptimisticException;
|
import org.apache.openjpa.util.OptimisticException;
|
||||||
|
|
||||||
|
@ -139,6 +140,8 @@ public abstract class AbstractUpdateManager
|
||||||
RowManager rowMgr, JDBCStore store, Collection exceps,
|
RowManager rowMgr, JDBCStore store, Collection exceps,
|
||||||
Collection customs) {
|
Collection customs) {
|
||||||
try {
|
try {
|
||||||
|
BitSet dirty;
|
||||||
|
|
||||||
if (sm.getPCState() == PCState.PNEW && !sm.isFlushed()) {
|
if (sm.getPCState() == PCState.PNEW && !sm.isFlushed()) {
|
||||||
insert(sm, (ClassMapping) sm.getMetaData(), rowMgr, store,
|
insert(sm, (ClassMapping) sm.getMetaData(), rowMgr, store,
|
||||||
customs);
|
customs);
|
||||||
|
@ -146,16 +149,7 @@ public abstract class AbstractUpdateManager
|
||||||
|| sm.getPCState() == PCState.PDELETED) {
|
|| sm.getPCState() == PCState.PDELETED) {
|
||||||
delete(sm, (ClassMapping) sm.getMetaData(), rowMgr, store,
|
delete(sm, (ClassMapping) sm.getMetaData(), rowMgr, store,
|
||||||
customs);
|
customs);
|
||||||
} else if ((sm.getPCState() == PCState.PDIRTY && (!sm.isFlushed() || sm
|
} else if ((dirty = ImplHelper.getUpdateFields(sm)) != null) {
|
||||||
.isFlushedDirty()))
|
|
||||||
|| (sm.getPCState() == PCState.PNEW && sm.isFlushedDirty())) {
|
|
||||||
BitSet dirty = sm.getDirty();
|
|
||||||
if (sm.isFlushed()) {
|
|
||||||
dirty = (BitSet) dirty.clone();
|
|
||||||
dirty.andNot(sm.getFlushed());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dirty.length() > 0)
|
|
||||||
update(sm, dirty, (ClassMapping) sm.getMetaData(), rowMgr,
|
update(sm, dirty, (ClassMapping) sm.getMetaData(), rowMgr,
|
||||||
store, customs);
|
store, customs);
|
||||||
} else if (sm.isVersionUpdateRequired()) {
|
} else if (sm.isVersionUpdateRequired()) {
|
||||||
|
|
|
@ -138,7 +138,7 @@ public abstract class ColumnVersionStrategy
|
||||||
|
|
||||||
// set where and update conditions on row
|
// set where and update conditions on row
|
||||||
for (int i = 0; i < cols.length; i++) {
|
for (int i = 0; i < cols.length; i++) {
|
||||||
if (curVersion != null)
|
if (curVersion != null && sm.isVersionCheckRequired())
|
||||||
row.whereObject(cols[i], curVersion);
|
row.whereObject(cols[i], curVersion);
|
||||||
if (vers.getColumnIO().isUpdatable(i, nextVersion == null))
|
if (vers.getColumnIO().isUpdatable(i, nextVersion == null))
|
||||||
row.setObject(cols[i], nextVersion);
|
row.setObject(cols[i], nextVersion);
|
||||||
|
|
|
@ -101,6 +101,7 @@ public class StateComparisonVersionStrategy
|
||||||
// db values match our previous image
|
// db values match our previous image
|
||||||
FieldMapping[] fields = (FieldMapping[]) sm.getMetaData().getFields();
|
FieldMapping[] fields = (FieldMapping[]) sm.getMetaData().getFields();
|
||||||
Row row;
|
Row row;
|
||||||
|
if (sm.isVersionCheckRequired()) {
|
||||||
for (int i = 0, max = loaded.length(); i < max; i++) {
|
for (int i = 0, max = loaded.length(); i < max; i++) {
|
||||||
if (!loaded.get(i))
|
if (!loaded.get(i))
|
||||||
continue;
|
continue;
|
||||||
|
@ -120,10 +121,11 @@ public class StateComparisonVersionStrategy
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// set WHERE criteria matching the previous state image so the
|
// set WHERE criteria matching the previous state image so the
|
||||||
// update will fail if any changes have been made by another trans
|
// update will fail for any changes made by another transaction
|
||||||
fields[i].where(sm, store, rm, state[i]);
|
fields[i].where(sm, store, rm, state[i]);
|
||||||
row.setFailedObject(sm.getManagedInstance());
|
row.setFailedObject(sm.getManagedInstance());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
sm.setNextVersion(nextState);
|
sm.setNextVersion(nextState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ public class Compatibility {
|
||||||
private boolean _copyIds = false;
|
private boolean _copyIds = false;
|
||||||
private boolean _closeOnCommit = true;
|
private boolean _closeOnCommit = true;
|
||||||
private boolean _quotedNumbers = false;
|
private boolean _quotedNumbers = false;
|
||||||
|
private boolean _nonOptimisticVersionCheck = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to require exact identity value types when creating object
|
* Whether to require exact identity value types when creating object
|
||||||
|
@ -136,4 +137,24 @@ public class Compatibility {
|
||||||
public void setCloseOnManagedCommit(boolean close) {
|
public void setCloseOnManagedCommit(boolean close) {
|
||||||
_closeOnCommit = close;
|
_closeOnCommit = close;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to perform a version check on instances being updated
|
||||||
|
* in a datastore transaction. Version of OpenJPA prior to 4.1 always
|
||||||
|
* forced a version check.
|
||||||
|
*/
|
||||||
|
public void setNonOptimisticVersionCheck
|
||||||
|
(boolean nonOptimisticVersionCheck) {
|
||||||
|
_nonOptimisticVersionCheck = nonOptimisticVersionCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to perform a version check on instances being updated
|
||||||
|
* in a datastore transaction. Version of OpenJPA prior to 4.1 always
|
||||||
|
* forced a version check.
|
||||||
|
*/
|
||||||
|
public boolean getNonOptimisticVersionCheck() {
|
||||||
|
return _nonOptimisticVersionCheck;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.apache.openjpa.meta.ValueMetaData;
|
||||||
import org.apache.openjpa.meta.ValueStrategies;
|
import org.apache.openjpa.meta.ValueStrategies;
|
||||||
import org.apache.openjpa.util.ApplicationIds;
|
import org.apache.openjpa.util.ApplicationIds;
|
||||||
import org.apache.openjpa.util.Exceptions;
|
import org.apache.openjpa.util.Exceptions;
|
||||||
|
import org.apache.openjpa.util.ImplHelper;
|
||||||
import org.apache.openjpa.util.InternalException;
|
import org.apache.openjpa.util.InternalException;
|
||||||
import org.apache.openjpa.util.InvalidStateException;
|
import org.apache.openjpa.util.InvalidStateException;
|
||||||
import org.apache.openjpa.util.ObjectNotFoundException;
|
import org.apache.openjpa.util.ObjectNotFoundException;
|
||||||
|
@ -2926,7 +2927,23 @@ public class StateManagerImpl
|
||||||
* Returns whether this instance needs a version check.
|
* Returns whether this instance needs a version check.
|
||||||
*/
|
*/
|
||||||
public boolean isVersionCheckRequired() {
|
public boolean isVersionCheckRequired() {
|
||||||
return (_flags & FLAG_VERSION_CHECK) > 0;
|
|
||||||
|
// explicit flag for version check
|
||||||
|
if ((_flags & FLAG_VERSION_CHECK) > 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// need to check version if we have any dirty fields, unless we
|
||||||
|
// are in a datastore transaction
|
||||||
|
if (ImplHelper.getUpdateFields(this) != null) {
|
||||||
|
if (_broker.getOptimistic()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return _broker.getConfiguration().
|
||||||
|
getCompatibilityInstance().getNonOptimisticVersionCheck();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.apache.openjpa.util;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.BitSet;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
@ -166,6 +167,30 @@ public class ImplHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fields of the state that require an update.
|
||||||
|
*
|
||||||
|
* @param sm the state to check
|
||||||
|
* @return the BitSet of fields that need update, or null if none
|
||||||
|
*/
|
||||||
|
public static BitSet getUpdateFields(OpenJPAStateManager sm) {
|
||||||
|
|
||||||
|
if ((sm.getPCState() == PCState.PDIRTY
|
||||||
|
&& (!sm.isFlushed() || sm.isFlushedDirty()))
|
||||||
|
|| (sm.getPCState() == PCState.PNEW && sm.isFlushedDirty())) {
|
||||||
|
BitSet dirty = sm.getDirty();
|
||||||
|
if (sm.isFlushed()) {
|
||||||
|
dirty = (BitSet) dirty.clone();
|
||||||
|
dirty.andNot(sm.getFlushed());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirty.length() > 0)
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close the given resource. The resource can be an extent iterator,
|
* Close the given resource. The resource can be an extent iterator,
|
||||||
* query result, large result set relation, or any closeable OpenJPA
|
* query result, large result set relation, or any closeable OpenJPA
|
||||||
|
|
Loading…
Reference in New Issue