mirror of https://github.com/apache/openjpa.git
OPENJPA-1253: support non-default bi-directional one-to-many using foreign key strategy to find/query from the ower's side
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@817831 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
01c26a9e21
commit
6f1b9627fe
|
@ -83,8 +83,10 @@ public class RelationFieldStrategy
|
|||
(RelationFieldStrategy.class);
|
||||
|
||||
private Boolean _fkOid = null;
|
||||
boolean _isBiOneToManyJoinTable = false;
|
||||
|
||||
private int _biOneToManyJoinTable = -1;
|
||||
private ForeignKey _biOneToManyJoinFK = null;
|
||||
private ForeignKey _biOneToManyElemFK = null;
|
||||
|
||||
public void map(boolean adapt) {
|
||||
if (field.getTypeCode() != JavaTypes.PC || field.isEmbeddedPC())
|
||||
throw new MetaDataException(_loc.get("not-relation", field));
|
||||
|
@ -140,25 +142,8 @@ public class RelationFieldStrategy
|
|||
OpenJPAConfiguration conf = field.getRepository().getConfiguration();
|
||||
boolean isNonDefaultMappingAllowed = field.getRepository().
|
||||
getMetaDataFactory().getDefaults().isNonDefaultMappingAllowed(conf);
|
||||
if (isNonDefaultMappingAllowed) {
|
||||
ClassMapping inverse = field.getValueMapping().getTypeMapping();
|
||||
FieldMapping[] fmds = inverse.getFieldMappings();
|
||||
for (int i = 0; i < fmds.length; i++) {
|
||||
if (field == fmds[i].getMappedByMapping()) {
|
||||
int typeCode = fmds[i].getDeclaredTypeCode();
|
||||
if (typeCode == JavaTypes.ARRAY ||
|
||||
typeCode == JavaTypes.COLLECTION ||
|
||||
typeCode == JavaTypes.MAP) {
|
||||
// this is a bi-directional oneToMany relation with
|
||||
// @JoinTable annotation ==> join table strategy
|
||||
// ==> should not mapped in the owner's table
|
||||
FieldMappingInfo info = fmds[i].getMappingInfo();
|
||||
_isBiOneToManyJoinTable = (info.getTableName() != null ? true : false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isNonDefaultMappingAllowed)
|
||||
getBiOneToManyInfo();
|
||||
}
|
||||
|
||||
// this is necessary to support openjpa 3 mappings, which didn't
|
||||
|
@ -183,7 +168,7 @@ public class RelationFieldStrategy
|
|||
if (field.getMappedByIdValue() != null)
|
||||
setMappedByIdColumns();
|
||||
|
||||
if (!_isBiOneToManyJoinTable) {
|
||||
if (_biOneToManyJoinTable == -1) {
|
||||
ForeignKey fk = vinfo.getTypeJoin(field, field.getName(), true,
|
||||
adapt);
|
||||
field.setForeignKey(fk);
|
||||
|
@ -295,7 +280,7 @@ public class RelationFieldStrategy
|
|||
else {
|
||||
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
|
||||
if (row != null) {
|
||||
if (!_isBiOneToManyJoinTable)
|
||||
if (_biOneToManyJoinTable == -1)
|
||||
field.setForeignKey(row, rel);
|
||||
// this is for bi-directional maps, the key and value of the
|
||||
// map are stored in the table of the mapped-by entity
|
||||
|
@ -382,12 +367,29 @@ public class RelationFieldStrategy
|
|||
Row.ACTION_DELETE : Row.ACTION_UPDATE;
|
||||
Row row = field.getRow(sm, store, rm, action);
|
||||
if (row != null) {
|
||||
if (!_isBiOneToManyJoinTable)
|
||||
if (_biOneToManyJoinTable == -1)
|
||||
field.setForeignKey(row, rel);
|
||||
// this is for bi-directional maps, the key and value of the
|
||||
// map are stored in the table of the mapped-by entity
|
||||
setMapKey(sm, rel, store, row);
|
||||
}
|
||||
|
||||
if (_biOneToManyJoinTable != -1) { // also need to update the join table
|
||||
PersistenceCapable inversePC = (PersistenceCapable)sm.fetchObject(_biOneToManyJoinTable);
|
||||
Row secondaryRow = null;
|
||||
if (inversePC != null) {
|
||||
secondaryRow = rm.getSecondaryRow(_biOneToManyJoinFK.getTable(),
|
||||
Row.ACTION_INSERT);
|
||||
secondaryRow.setForeignKey(_biOneToManyElemFK, null, sm);
|
||||
secondaryRow.setForeignKey(_biOneToManyJoinFK, null,
|
||||
(OpenJPAStateManager)inversePC.pcGetStateManager());
|
||||
} else {
|
||||
secondaryRow = rm.getSecondaryRow(_biOneToManyJoinFK.getTable(),
|
||||
Row.ACTION_DELETE);
|
||||
secondaryRow.setForeignKey(_biOneToManyElemFK, null, sm);
|
||||
}
|
||||
rm.flushSecondaryRow(secondaryRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -560,6 +562,8 @@ public class RelationFieldStrategy
|
|||
*/
|
||||
private void selectEagerParallel(Select sel, ClassMapping cls,
|
||||
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
|
||||
if (_biOneToManyJoinTable != -1)
|
||||
return;
|
||||
sel.selectPrimaryKey(field.getDefiningMapping());
|
||||
// set a variable name that does not conflict with any in the query;
|
||||
// using a variable guarantees that the selected data will use different
|
||||
|
@ -573,7 +577,7 @@ public class RelationFieldStrategy
|
|||
|
||||
public void selectEagerJoin(Select sel, OpenJPAStateManager sm,
|
||||
JDBCStore store, JDBCFetchConfiguration fetch, int eagerMode) {
|
||||
if (_isBiOneToManyJoinTable)
|
||||
if (_biOneToManyJoinTable != -1)
|
||||
return;
|
||||
|
||||
// limit the eager mode to single on recursive eager fetching b/c
|
||||
|
@ -678,6 +682,8 @@ public class RelationFieldStrategy
|
|||
public void loadEagerJoin(OpenJPAStateManager sm, JDBCStore store,
|
||||
JDBCFetchConfiguration fetch, Result res)
|
||||
throws SQLException {
|
||||
if (_biOneToManyJoinTable != -1)
|
||||
return;
|
||||
ClassMapping cls = field.getIndependentTypeMappings()[0];
|
||||
|
||||
// for inverseEager field
|
||||
|
@ -725,7 +731,7 @@ public class RelationFieldStrategy
|
|||
// get the related object's oid
|
||||
ClassMapping relMapping = field.getTypeMapping();
|
||||
Object oid = null;
|
||||
if (relMapping.isMapped() && !_isBiOneToManyJoinTable) {
|
||||
if (relMapping.isMapped() && _biOneToManyJoinTable == -1) {
|
||||
oid = relMapping.getObjectId(store, res, field.getForeignKey(),
|
||||
field.getPolymorphic() != ValueMapping.POLY_FALSE, null);
|
||||
} else {
|
||||
|
@ -791,10 +797,18 @@ public class RelationFieldStrategy
|
|||
sel.whereForeignKey(field.getForeignKey(rels[idx]),
|
||||
sm.getObjectId(), field.getDefiningMapping(), store);
|
||||
else {
|
||||
resJoins[idx] = sel.newJoins().joinRelation(field.getName(),
|
||||
field.getForeignKey(rels[idx]), rels[idx],
|
||||
field.getSelectSubclasses(), false, false);
|
||||
field.wherePrimaryKey(sel, sm, store);
|
||||
if (_biOneToManyJoinTable == -1) {
|
||||
resJoins[idx] = sel.newJoins().joinRelation(field.getName(),
|
||||
field.getForeignKey(rels[idx]), rels[idx],
|
||||
field.getSelectSubclasses(), false, false);
|
||||
field.wherePrimaryKey(sel, sm, store);
|
||||
} else {
|
||||
resJoins[idx] = sel.newJoins().joinRelation(null,
|
||||
getBiOneToManyJoinFK(), rels[idx],
|
||||
field.getSelectSubclasses(), false, false);
|
||||
sel.whereForeignKey(getBiOneToManyElemFK(), sm.getObjectId(),
|
||||
field.getDefiningMapping(), store);
|
||||
}
|
||||
}
|
||||
sel.select(rels[idx], subs, store, fetch, fetch.EAGER_JOIN,
|
||||
resJoins[idx]);
|
||||
|
@ -813,6 +827,43 @@ public class RelationFieldStrategy
|
|||
}
|
||||
}
|
||||
|
||||
private ForeignKey getBiOneToManyJoinFK() {
|
||||
if (_biOneToManyJoinFK == null) {
|
||||
getBiOneToManyInfo();
|
||||
}
|
||||
return _biOneToManyJoinFK;
|
||||
}
|
||||
|
||||
private ForeignKey getBiOneToManyElemFK() {
|
||||
if (_biOneToManyElemFK == null) {
|
||||
getBiOneToManyInfo();
|
||||
}
|
||||
return _biOneToManyElemFK;
|
||||
}
|
||||
|
||||
private void getBiOneToManyInfo() {
|
||||
ClassMapping inverse = field.getValueMapping().getTypeMapping();
|
||||
FieldMapping[] fmds = inverse.getFieldMappings();
|
||||
for (int i = 0; i < fmds.length; i++) {
|
||||
if (field == fmds[i].getMappedByMapping()) {
|
||||
int typeCode = fmds[i].getDeclaredTypeCode();
|
||||
if (typeCode == JavaTypes.ARRAY ||
|
||||
typeCode == JavaTypes.COLLECTION ||
|
||||
typeCode == JavaTypes.MAP) {
|
||||
// this is a bi-directional oneToMany relation with
|
||||
// @JoinTable annotation ==> join table strategy
|
||||
// ==> should not mapped in the owner's table
|
||||
FieldMappingInfo info = fmds[i].getMappingInfo();
|
||||
if (info.getTableName() != null)
|
||||
_biOneToManyJoinTable = i;
|
||||
_biOneToManyElemFK = fmds[i].getElementMapping().getForeignKey();
|
||||
_biOneToManyJoinFK = fmds[i].getJoinForeignKey();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object toDataStoreValue(Object val, JDBCStore store) {
|
||||
return RelationStrategies.toDataStoreValue(field, val, store);
|
||||
}
|
||||
|
|
|
@ -369,11 +369,17 @@ extends AbstractCachedEMFTestCase {
|
|||
em.clear();
|
||||
|
||||
//query
|
||||
Query q = em.createQuery("SELECT u FROM Bi_1ToM_JT u");
|
||||
Query q = em.createQuery("SELECT b FROM Bi_1ToM_JT b where b.name = 'newName'");
|
||||
Bi_1ToM_JT b1 = (Bi_1ToM_JT)q.getSingleResult();
|
||||
assertEquals(b, b1);
|
||||
em.clear();
|
||||
|
||||
//query
|
||||
q = em.createQuery("SELECT c FROM EntityC_B1MJT c");
|
||||
List<EntityC_B1MJT> cs1 = q.getResultList();
|
||||
assertEquals(2, cs1.size());
|
||||
em.clear();
|
||||
|
||||
//find
|
||||
long id = b1.getId();
|
||||
Bi_1ToM_JT b2 = em.find(Bi_1ToM_JT.class, id);
|
||||
|
|
Loading…
Reference in New Issue