mirror of https://github.com/apache/openjpa.git
Merge fixes from Kodo 4.0 line.
git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@453796 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ac1679d41c
commit
433475f6ad
|
@ -1634,7 +1634,7 @@ public abstract class MappingInfo {
|
||||||
if (col.getDefaultString() != null)
|
if (col.getDefaultString() != null)
|
||||||
copy.setDefaultString(col.getDefaultString());
|
copy.setDefaultString(col.getDefaultString());
|
||||||
if (col.isNotNull() && !col.isPrimaryKey()
|
if (col.isNotNull() && !col.isPrimaryKey()
|
||||||
&& !isPrimitive(col.getJavaType()))
|
&& (!isPrimitive(col.getJavaType()) || isForeignKey(col)))
|
||||||
copy.setNotNull(true);
|
copy.setNotNull(true);
|
||||||
|
|
||||||
// set type name if not default
|
// set type name if not default
|
||||||
|
@ -1674,6 +1674,21 @@ public abstract class MappingInfo {
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the given column belongs to a foreign key.
|
||||||
|
*/
|
||||||
|
private static boolean isForeignKey(Column col)
|
||||||
|
{
|
||||||
|
if (col.getTable() == null)
|
||||||
|
return false;
|
||||||
|
ForeignKey[] fks = col.getTable().getForeignKeys();
|
||||||
|
for (int i = 0; i < fks.length; i++)
|
||||||
|
if (fks[i].containsColumn(col)
|
||||||
|
|| fks[i].containsConstantColumn(col))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the given type code represents a primitive.
|
* Return true if the given type code represents a primitive.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -180,7 +180,7 @@ public class RelationFieldStrategy
|
||||||
OpenJPAStateManager rel = RelationStrategies.getStateManager
|
OpenJPAStateManager rel = RelationStrategies.getStateManager
|
||||||
(sm.fetchObjectField(field.getIndex()), store.getContext());
|
(sm.fetchObjectField(field.getIndex()), store.getContext());
|
||||||
if (field.getJoinDirection() == field.JOIN_INVERSE)
|
if (field.getJoinDirection() == field.JOIN_INVERSE)
|
||||||
updateInverse(sm, rel, store, rm, sm);
|
updateInverse(sm, rel, store, rm);
|
||||||
else {
|
else {
|
||||||
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
|
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
|
||||||
if (row != null)
|
if (row != null)
|
||||||
|
@ -198,7 +198,7 @@ public class RelationFieldStrategy
|
||||||
|
|
||||||
if (field.getJoinDirection() == field.JOIN_INVERSE) {
|
if (field.getJoinDirection() == field.JOIN_INVERSE) {
|
||||||
nullInverse(sm, rm);
|
nullInverse(sm, rm);
|
||||||
updateInverse(sm, rel, store, rm, sm);
|
updateInverse(sm, rel, store, rm);
|
||||||
} else {
|
} else {
|
||||||
Row row = field.getRow(sm, store, rm, Row.ACTION_UPDATE);
|
Row row = field.getRow(sm, store, rm, Row.ACTION_UPDATE);
|
||||||
if (row != null)
|
if (row != null)
|
||||||
|
@ -215,7 +215,7 @@ public class RelationFieldStrategy
|
||||||
if (sm.getLoaded().get(field.getIndex())) {
|
if (sm.getLoaded().get(field.getIndex())) {
|
||||||
OpenJPAStateManager rel = RelationStrategies.getStateManager(sm.
|
OpenJPAStateManager rel = RelationStrategies.getStateManager(sm.
|
||||||
fetchObjectField(field.getIndex()), store.getContext());
|
fetchObjectField(field.getIndex()), store.getContext());
|
||||||
updateInverse(sm, rel, store, rm, null);
|
updateInverse(sm, rel, store, rm);
|
||||||
} else
|
} else
|
||||||
nullInverse(sm, rm);
|
nullInverse(sm, rm);
|
||||||
} else {
|
} else {
|
||||||
|
@ -241,6 +241,9 @@ public class RelationFieldStrategy
|
||||||
*/
|
*/
|
||||||
private void nullInverse(OpenJPAStateManager sm, RowManager rm)
|
private void nullInverse(OpenJPAStateManager sm, RowManager rm)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
|
if (field.getUseClassCriteria())
|
||||||
|
return;
|
||||||
|
|
||||||
ForeignKey fk = field.getForeignKey();
|
ForeignKey fk = field.getForeignKey();
|
||||||
ColumnIO io = field.getColumnIO();
|
ColumnIO io = field.getColumnIO();
|
||||||
if (!io.isAnyUpdatable(fk, true))
|
if (!io.isAnyUpdatable(fk, true))
|
||||||
|
@ -260,11 +263,9 @@ public class RelationFieldStrategy
|
||||||
* with the given object.
|
* with the given object.
|
||||||
*/
|
*/
|
||||||
private void updateInverse(OpenJPAStateManager sm, OpenJPAStateManager rel,
|
private void updateInverse(OpenJPAStateManager sm, OpenJPAStateManager rel,
|
||||||
JDBCStore store, RowManager rm, OpenJPAStateManager sm2)
|
JDBCStore store, RowManager rm)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
// nothing to do if inverse is null or about to be deleted
|
if (rel == null)
|
||||||
//### should we throw an exception if the inverse is null?
|
|
||||||
if (rel == null || rel.isDeleted())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ForeignKey fk = field.getForeignKey();
|
ForeignKey fk = field.getForeignKey();
|
||||||
|
@ -272,11 +273,17 @@ public class RelationFieldStrategy
|
||||||
|
|
||||||
int action;
|
int action;
|
||||||
if (rel.isNew() && !rel.isFlushed()) {
|
if (rel.isNew() && !rel.isFlushed()) {
|
||||||
if (sm2 == null || !io.isAnyInsertable(fk, false))
|
if (sm.isDeleted() || !io.isAnyInsertable(fk, false))
|
||||||
return;
|
return;
|
||||||
action = Row.ACTION_INSERT;
|
action = Row.ACTION_INSERT;
|
||||||
|
} else if (rel.isDeleted()) {
|
||||||
|
if (rel.isFlushed() || !sm.isDeleted())
|
||||||
|
return;
|
||||||
|
action = Row.ACTION_DELETE;
|
||||||
} else {
|
} else {
|
||||||
if (!io.isAnyUpdatable(fk, sm2 == null))
|
if (sm.isDeleted())
|
||||||
|
sm = null;
|
||||||
|
if (!io.isAnyUpdatable(fk, sm == null))
|
||||||
return;
|
return;
|
||||||
action = Row.ACTION_UPDATE;
|
action = Row.ACTION_UPDATE;
|
||||||
}
|
}
|
||||||
|
@ -306,7 +313,7 @@ public class RelationFieldStrategy
|
||||||
row.wherePrimaryKey(rel);
|
row.wherePrimaryKey(rel);
|
||||||
|
|
||||||
// update the inverse pointer with our oid value
|
// update the inverse pointer with our oid value
|
||||||
row.setForeignKey(fk, io, sm2);
|
row.setForeignKey(fk, io, sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
|
public int supportsSelect(Select sel, int type, OpenJPAStateManager sm,
|
||||||
|
|
|
@ -216,23 +216,32 @@ public abstract class RelationToManyInverseKeyFieldStrategy
|
||||||
|
|
||||||
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
|
public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
if (field.getMappedBy() != null
|
if (field.getMappedBy() != null)
|
||||||
|| field.getElementMapping().getUseClassCriteria())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// if nullable, null any existing inverse columns that refer to this obj
|
||||||
ValueMapping elem = field.getElementMapping();
|
ValueMapping elem = field.getElementMapping();
|
||||||
ColumnIO io = elem.getColumnIO();
|
ColumnIO io = elem.getColumnIO();
|
||||||
ForeignKey fk = elem.getForeignKey();
|
ForeignKey fk = elem.getForeignKey();
|
||||||
if (!io.isAnyUpdatable(fk, true))
|
if (!elem.getUseClassCriteria() && io.isAnyUpdatable(fk, true)) {
|
||||||
|
assertInversable();
|
||||||
|
Row row = rm.getAllRows(fk.getTable(), Row.ACTION_UPDATE);
|
||||||
|
row.setForeignKey(fk, io, null);
|
||||||
|
row.whereForeignKey(fk, sm);
|
||||||
|
rm.flushAllRows(row);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sm.getLoaded().get(field.getIndex()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if the fk doesn't enforce it, null any existing inverse columns
|
// update fk on each field value row
|
||||||
// that refer to this obj
|
ClassMapping rel = field.getElementMapping().getTypeMapping();
|
||||||
assertInversable();
|
StoreContext ctx = store.getContext();
|
||||||
Row row = rm.getAllRows(fk.getTable(), Row.ACTION_UPDATE);
|
Collection objs = toCollection(sm.fetchObject(field.getIndex()));
|
||||||
row.setForeignKey(fk, io, null);
|
if (objs != null && !objs.isEmpty())
|
||||||
row.whereForeignKey(fk, sm);
|
for (Iterator itr = objs.iterator(); itr.hasNext();)
|
||||||
rm.flushAllRows(row);
|
updateInverse (ctx, itr.next(), rel, rm, sm, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -244,7 +253,7 @@ public abstract class RelationToManyInverseKeyFieldStrategy
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
OpenJPAStateManager invsm = RelationStrategies.getStateManager(inverse,
|
OpenJPAStateManager invsm = RelationStrategies.getStateManager(inverse,
|
||||||
ctx);
|
ctx);
|
||||||
if (invsm == null || invsm.isDeleted())
|
if (invsm == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ValueMapping elem = field.getElementMapping();
|
ValueMapping elem = field.getElementMapping();
|
||||||
|
@ -257,12 +266,21 @@ public abstract class RelationToManyInverseKeyFieldStrategy
|
||||||
boolean orderWriteable;
|
boolean orderWriteable;
|
||||||
if (invsm.isNew() && !invsm.isFlushed()) {
|
if (invsm.isNew() && !invsm.isFlushed()) {
|
||||||
// no need to null inverse columns of new instance
|
// no need to null inverse columns of new instance
|
||||||
if (sm == null)
|
if (sm == null || sm.isDeleted())
|
||||||
return;
|
return;
|
||||||
writeable = io.isAnyInsertable(fk, false);
|
writeable = io.isAnyInsertable(fk, false);
|
||||||
orderWriteable = _orderInsert;
|
orderWriteable = _orderInsert;
|
||||||
action = Row.ACTION_INSERT;
|
action = Row.ACTION_INSERT;
|
||||||
|
} else if (invsm.isDeleted()) {
|
||||||
|
// no need to null inverse columns of deleted instance
|
||||||
|
if (invsm.isFlushed() || sm == null || !sm.isDeleted())
|
||||||
|
return;
|
||||||
|
writeable = true;
|
||||||
|
orderWriteable = false;
|
||||||
|
action = Row.ACTION_DELETE;
|
||||||
} else {
|
} else {
|
||||||
|
if (sm != null && sm.isDeleted())
|
||||||
|
sm = null;
|
||||||
writeable = io.isAnyUpdatable(fk, sm == null);
|
writeable = io.isAnyUpdatable(fk, sm == null);
|
||||||
orderWriteable = field.getOrderColumnIO().isUpdatable
|
orderWriteable = field.getOrderColumnIO().isUpdatable
|
||||||
(order, sm == null);
|
(order, sm == null);
|
||||||
|
|
|
@ -80,7 +80,8 @@ public class ColumnIO {
|
||||||
* Return true if any columns for the given key are insertable.
|
* Return true if any columns for the given key are insertable.
|
||||||
*/
|
*/
|
||||||
public boolean isAnyInsertable(ForeignKey fk, boolean nullValue) {
|
public boolean isAnyInsertable(ForeignKey fk, boolean nullValue) {
|
||||||
return isAny(fk, _unInsertable, _unNullInsertable, nullValue);
|
return isAny(fk, _unInsertable, _unNullInsertable, nullValue)
|
||||||
|
&& (!nullValue || fk.isLogical() || isNullable(fk));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,7 +102,8 @@ public class ColumnIO {
|
||||||
* Return true if all columns for the given key are insertable.
|
* Return true if all columns for the given key are insertable.
|
||||||
*/
|
*/
|
||||||
public boolean isAllInsertable(ForeignKey fk, boolean nullValue) {
|
public boolean isAllInsertable(ForeignKey fk, boolean nullValue) {
|
||||||
return isAll(fk, _unInsertable, _unNullInsertable, nullValue);
|
return isAll(fk, _unInsertable, _unNullInsertable, nullValue)
|
||||||
|
&& (!nullValue || fk.isLogical() || isNullable(fk));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -152,7 +154,8 @@ public class ColumnIO {
|
||||||
* Return true if any columns for the given key are updatable.
|
* Return true if any columns for the given key are updatable.
|
||||||
*/
|
*/
|
||||||
public boolean isAnyUpdatable(ForeignKey fk, boolean nullValue) {
|
public boolean isAnyUpdatable(ForeignKey fk, boolean nullValue) {
|
||||||
return isAny(fk, _unUpdatable, _unNullUpdatable, nullValue);
|
return isAny(fk, _unUpdatable, _unNullUpdatable, nullValue)
|
||||||
|
&& (!nullValue || fk.isLogical() || isNullable(fk));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -173,7 +176,8 @@ public class ColumnIO {
|
||||||
* Return true if all columns for the given key are updatable.
|
* Return true if all columns for the given key are updatable.
|
||||||
*/
|
*/
|
||||||
public boolean isAllUpdatable(ForeignKey fk, boolean nullValue) {
|
public boolean isAllUpdatable(ForeignKey fk, boolean nullValue) {
|
||||||
return isAll(fk, _unUpdatable, _unNullUpdatable, nullValue);
|
return isAll(fk, _unUpdatable, _unNullUpdatable, nullValue)
|
||||||
|
&& (!nullValue || fk.isLogical() || isNullable(fk));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -284,4 +288,15 @@ public class ColumnIO {
|
||||||
return property & ~(2 << col);
|
return property & ~(2 << col);
|
||||||
return property | (2 << col);
|
return property | (2 << col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the given foreign key is nullable.
|
||||||
|
*/
|
||||||
|
private boolean isNullable(ForeignKey fk) {
|
||||||
|
Column[] cols = fk.getColumns();
|
||||||
|
for (int i = 0; i < cols.length; i++)
|
||||||
|
if (cols[i].isNotNull() || cols[i].isPrimaryKey())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,7 +203,7 @@ public class ForeignKey
|
||||||
seen.add(this);
|
seen.add(this);
|
||||||
for (int i = 0; i < cols.length; i++) {
|
for (int i = 0; i < cols.length; i++) {
|
||||||
for (int j = 0; j < fks.length; j++) {
|
for (int j = 0; j < fks.length; j++) {
|
||||||
if (fks[j].getPrimaryKeyColumn(cols[i]) == null)
|
if (!fks[j].containsColumn(cols[i]))
|
||||||
continue;
|
continue;
|
||||||
if (!seen.contains(fks[j])
|
if (!seen.contains(fks[j])
|
||||||
&& fks[j].isPrimaryKeyAutoAssigned(seen)) {
|
&& fks[j].isPrimaryKeyAutoAssigned(seen)) {
|
||||||
|
|
|
@ -390,10 +390,11 @@ public class PCEnhancer {
|
||||||
setter = _pc.getDeclaredMethod(getSetterName(fmds[i]),
|
setter = _pc.getDeclaredMethod(getSetterName(fmds[i]),
|
||||||
new Class[]{ fmds[i].getDeclaredType() });
|
new Class[]{ fmds[i].getDeclaredType() });
|
||||||
if (setter == null) {
|
if (setter == null) {
|
||||||
if (returned == null)
|
if (returned == null) {
|
||||||
addViolation("property-no-setter",
|
addViolation("property-no-setter",
|
||||||
new Object[]{ fmds[i] }, true);
|
new Object[]{ fmds[i] }, true);
|
||||||
else {
|
continue;
|
||||||
|
} else {
|
||||||
// create synthetic setter
|
// create synthetic setter
|
||||||
setter = _pc.declareMethod(getSetterName(fmds[i]),
|
setter = _pc.declareMethod(getSetterName(fmds[i]),
|
||||||
void.class, new Class[]{ fmds[i].getDeclaredType() });
|
void.class, new Class[]{ fmds[i].getDeclaredType() });
|
||||||
|
@ -419,10 +420,9 @@ public class PCEnhancer {
|
||||||
_backingFields.put(setter.getName(), assigned.getName());
|
_backingFields.put(setter.getName(), assigned.getName());
|
||||||
|
|
||||||
if (assigned != returned)
|
if (assigned != returned)
|
||||||
addViolation("property-setter-getter-mismatch",
|
addViolation("property-setter-getter-mismatch", new Object[]
|
||||||
new Object[]{ fmds[i], assigned.getName(),
|
{ fmds[i], assigned.getName(), (returned == null)
|
||||||
(returned == null) ? null : returned.getName() },
|
? null : returned.getName() }, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1928,8 +1928,7 @@ public class BrokerImpl
|
||||||
exceps = add(exceps,
|
exceps = add(exceps,
|
||||||
newFlushException(_store.flush(transactional)));
|
newFlushException(_store.flush(transactional)));
|
||||||
}
|
}
|
||||||
}
|
} finally {
|
||||||
finally {
|
|
||||||
_flags &= ~FLAG_STORE_FLUSHING;
|
_flags &= ~FLAG_STORE_FLUSHING;
|
||||||
|
|
||||||
if (reason == FLUSH_ROLLBACK)
|
if (reason == FLUSH_ROLLBACK)
|
||||||
|
@ -1942,21 +1941,24 @@ public class BrokerImpl
|
||||||
StateManagerImpl sm;
|
StateManagerImpl sm;
|
||||||
for (Iterator itr = transactional.iterator(); itr.hasNext();) {
|
for (Iterator itr = transactional.iterator(); itr.hasNext();) {
|
||||||
sm = (StateManagerImpl) itr.next();
|
sm = (StateManagerImpl) itr.next();
|
||||||
|
try {
|
||||||
|
// the state may have become transient, such as if
|
||||||
|
// it is embedded and the owner has been deleted during
|
||||||
|
// this flush process; bug #1100
|
||||||
|
if (sm.getPCState() == PCState.TRANSIENT)
|
||||||
|
continue;
|
||||||
|
|
||||||
// the state may have become transient, such as if
|
sm.afterFlush(reason);
|
||||||
// it is embedded and the owner has been deleted during
|
if (reason == FLUSH_INC) {
|
||||||
// this flush process; bug #1100
|
// if not about to clear trans cache for commit
|
||||||
if (sm.getPCState() == PCState.TRANSIENT)
|
// anyway, re-cache dirty objects with default soft
|
||||||
continue;
|
// refs; we don't need hard refs now that the
|
||||||
|
// changes have been flushed
|
||||||
sm.afterFlush(reason);
|
sm.proxyFields(true, false);
|
||||||
if (reason == FLUSH_INC) {
|
_transCache.flushed(sm);
|
||||||
// if not about to clear trans cache for commit anyway,
|
}
|
||||||
// re-cache dirty objects with default soft refs; we
|
} catch (Exception e) {
|
||||||
// don't need hard refs now that the changes have been
|
exceps = add(exceps, e);
|
||||||
// flushed
|
|
||||||
sm.proxyFields(true, false);
|
|
||||||
_transCache.flushed(sm);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ public class DetachManager
|
||||||
* needed. Return true if flushed/stored, false otherwise.
|
* needed. Return true if flushed/stored, false otherwise.
|
||||||
*/
|
*/
|
||||||
private static boolean flushDirty(StateManagerImpl sm) {
|
private static boolean flushDirty(StateManagerImpl sm) {
|
||||||
if (!sm.isDirty())
|
if (!sm.isDirty() || !sm.getBroker().isActive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// only flush if there are actually any dirty non-flushed fields
|
// only flush if there are actually any dirty non-flushed fields
|
||||||
|
|
|
@ -332,7 +332,6 @@ public abstract class XMLMetaDataParser extends DefaultHandler
|
||||||
// even if we want to validate, specify that it won't happen
|
// even if we want to validate, specify that it won't happen
|
||||||
// if we have neither a DocType not a Schema
|
// if we have neither a DocType not a Schema
|
||||||
Object schemaSource = getSchemaSource();
|
Object schemaSource = getSchemaSource();
|
||||||
|
|
||||||
if (schemaSource != null && _schemaBug) {
|
if (schemaSource != null && _schemaBug) {
|
||||||
if (_log != null && _log.isInfoEnabled())
|
if (_log != null && _log.isInfoEnabled())
|
||||||
_log.info(_loc.get("parser-schema-bug"));
|
_log.info(_loc.get("parser-schema-bug"));
|
||||||
|
|
Loading…
Reference in New Issue