in openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java [108:333]
public Object attach(AttachManager manager, Object toAttach,
ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner,
ValueMetaData ownerMeta, boolean explicit) {
BrokerImpl broker = manager.getBroker();
StateManagerImpl sm;
if (_embedded) {
if (_dirty.length () > 0)
owner.dirty(ownerMeta.getFieldMetaData().getIndex());
sm = (StateManagerImpl) broker.embed(_pc, _oid, owner, ownerMeta);
ImplHelper.toPersistenceCapable(toAttach, broker.getConfiguration())
.pcReplaceStateManager(this);
} else {
PCState state = (_dirty.length() > 0) ? PCState.PDIRTY
: PCState.PCLEAN;
sm = (StateManagerImpl) broker.copy(this, state);
}
PersistenceCapable pc = sm.getPersistenceCapable();
manager.setAttachedCopy(toAttach, pc);
manager.fireBeforeAttach(toAttach, meta);
// pre-load for efficiency: current field values for restore, dependent
// for delete
FieldMetaData[] fields = sm.getMetaData().getFields();
int restore = broker.getRestoreState();
boolean postLoadOnMerge = broker.getPostLoadOnMerge();
if (_dirty.length() > 0 || postLoadOnMerge) {
BitSet load = new BitSet(fields.length);
if (postLoadOnMerge && broker.getLifecycleEventManager().hasLoadListeners(pc, meta)) {
// load all fields
// this will automatically lead to invoking the PostLoad lifecycle event
// when the last field got set
// @see StateManagerImpl#postLoad(String, FetchConfiguration)
load.set(0, fields.length);
}
else {
for (int i = 0; i < fields.length; i++) {
if (!_dirty.get(i))
continue;
switch (fields[i].getDeclaredTypeCode()) {
case JavaTypes.ARRAY:
case JavaTypes.COLLECTION:
if (restore == RestoreState.RESTORE_ALL
|| fields[i].getElement().getCascadeDelete()
== ValueMetaData.CASCADE_AUTO)
load.set(i);
break;
case JavaTypes.MAP:
if (restore == RestoreState.RESTORE_ALL
|| fields[i].getElement().getCascadeDelete()
== ValueMetaData.CASCADE_AUTO
|| fields[i].getKey().getCascadeDelete()
== ValueMetaData.CASCADE_AUTO)
load.set(i);
break;
default:
if (restore != RestoreState.RESTORE_NONE
|| fields[i].getCascadeDelete()
== ValueMetaData.CASCADE_AUTO)
load.set(i);
}
}
}
if (!postLoadOnMerge) {
// prevent PostLoad callbacks even for the load operation
sm.setPostLoadCallback(false);
}
FetchConfiguration fc = broker.getFetchConfiguration();
sm.loadFields(load, fc, fc.getWriteLockLevel(), null);
}
Object origVersion = sm.getVersion();
sm.setVersion(_version);
BitSet loaded = sm.getLoaded();
int set = StateManager.SET_ATTACH;
sm.setPostLoadCallback(false);
for (int i = 0; i < fields.length; i++) {
if (!_loaded.get(i))
continue;
// don't reload already loaded non-mutable objects
if (!_dirty.get(i) && loaded.get(i) && ignoreLoaded(fields[i]))
continue;
provideField(i);
switch (fields[i].getDeclaredTypeCode()) {
case JavaTypes.BOOLEAN:
if (_dirty.get(i))
sm.settingBooleanField(pc, i,
(loaded.get(i)) && sm.fetchBooleanField(i),
longval == 1, set);
else
sm.storeBooleanField(i, longval == 1);
break;
case JavaTypes.BYTE:
if (_dirty.get(i))
sm.settingByteField(pc, i, (!loaded.get(i)) ? (byte) 0
: sm.fetchByteField(i), (byte) longval, set);
else
sm.storeByteField(i, (byte) longval);
break;
case JavaTypes.CHAR:
if (_dirty.get(i))
sm.settingCharField(pc, i, (!loaded.get(i)) ? (char) 0
: sm.fetchCharField(i), (char) longval, set);
else
sm.storeCharField(i, (char) longval);
break;
case JavaTypes.INT:
if (_dirty.get(i))
sm.settingIntField(pc, i, (!loaded.get(i)) ? 0
: sm.fetchIntField(i), (int) longval, set);
else
sm.storeIntField(i, (int) longval);
break;
case JavaTypes.LONG:
if (_dirty.get(i))
sm.settingLongField(pc, i, (!loaded.get(i)) ? 0L
: sm.fetchLongField(i), longval, set);
else
sm.storeLongField(i, longval);
break;
case JavaTypes.SHORT:
if (_dirty.get(i))
sm.settingShortField(pc, i,
(!loaded.get(i)) ? (short) 0 : sm.fetchShortField(i), (short) longval, set);
else
sm.storeShortField(i, (short) longval);
break;
case JavaTypes.FLOAT:
if (_dirty.get(i))
sm.settingFloatField(pc, i, (!loaded.get(i)) ? 0F
: sm.fetchFloatField(i), (float) dblval, set);
else
sm.storeFloatField(i, (float) dblval);
break;
case JavaTypes.DOUBLE:
if (_dirty.get(i))
sm.settingDoubleField(pc, i, (!loaded.get(i)) ? 0D
: sm.fetchDoubleField(i), dblval, set);
else
sm.storeDoubleField(i, dblval);
break;
case JavaTypes.STRING:
if (_dirty.get(i))
sm.settingStringField(pc, i, (!loaded.get(i)) ? null
: sm.fetchStringField(i), (String) objval, set);
else
sm.storeStringField(i, (String) objval);
objval = null;
break;
case JavaTypes.PC:
case JavaTypes.PC_UNTYPED:
if (fields[i].getCascadeAttach() == ValueMetaData
.CASCADE_NONE) {
// Use the attached copy of the object, if available
PersistenceCapable cpy = manager.getAttachedCopy(objval);
if (cpy != null) {
objval = cpy;
} else {
objval = getReference(manager, objval, sm, fields[i]);
}
}
else {
PersistenceCapable toPC = null;
if (objval != null && fields[i].isEmbeddedPC())
toPC = ImplHelper.toPersistenceCapable(objval,
broker.getConfiguration());
objval = manager.attach(objval, toPC, sm, fields[i],
false);
}
if (_dirty.get(i))
sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
: sm.fetchObjectField(i), objval, set);
else
sm.storeObjectField(i, objval);
objval = null;
break;
case JavaTypes.COLLECTION:
Collection coll = (Collection) objval;
objval = null;
if (coll != null)
coll = attachCollection(manager, coll, sm, fields[i]);
if (_dirty.get(i))
sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
: sm.fetchObjectField(i), coll, set);
else
sm.storeObjectField(i, coll);
break;
case JavaTypes.MAP:
Map map = (Map) objval;
objval = null;
if (map != null)
map = attachMap(manager, map, sm, fields[i]);
if (_dirty.get(i))
sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
: sm.fetchObjectField(i), map, set);
else
sm.storeObjectField(i, map);
break;
default:
if (_dirty.get(i))
sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
: sm.fetchObjectField(i), objval, set);
else
sm.storeObjectField(i, objval);
objval = null;
}
}
sm.setPostLoadCallback(true);
pc.pcReplaceStateManager(sm);
// if we were clean at least make sure a version check is done to
// prevent using old state
if (!sm.isVersionCheckRequired() && broker.isActive()
&& _version != origVersion && (origVersion == null
|| broker.getStoreManager().compareVersion(sm, _version,
origVersion) != StoreManager.VERSION_SAME)) {
broker.transactional(sm.getManagedInstance(), false,
manager.getBehavior());
}
return sm.getManagedInstance();
}