diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
index 6e00d1225..62c2353f8 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/FieldMapping.java
@@ -141,6 +141,15 @@ public class FieldMapping
return _fk.getTable();
if (_val.getForeignKey() != null)
return _val.getForeignKey().getTable();
+
+ // if this is a map of bi-directional relation,
+ // the column of this field should be in the table
+ // of the entity that is the value of the map
+ if (_val.getDeclaredTypeCode() == JavaTypes.MAP) {
+ ClassMapping meta = _elem.getDeclaredTypeMapping();
+ if (meta != null)
+ return meta.getTable();
+ }
return getDefiningMapping().getTable();
}
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
index 9a07efaa8..57e7c5ef2 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/MappingRepository.java
@@ -882,6 +882,11 @@ public class MappingRepository
return new RelationMapInverseKeyFieldStrategy();
return new RelationMapTableFieldStrategy();
}
+ //TODO: in JPA 2.0 if MapKeyClass type is not specified
+ // an exception is thrown. In OpenJpa 1.x, the map will
+ // be serialized to a blob (the null value returned by
+ // this method will lead to a strategy to serialize
+ // the map).
if (!krel && khandler == null)
break;
if (!vrel && vhandler == null)
@@ -901,6 +906,7 @@ public class MappingRepository
*/
protected FieldStrategy handlerCollectionStrategy(FieldMapping field,
ValueHandler ehandler, boolean installHandlers) {
+ // TODO: JPA 2.0 should ignore this flag and not to serialize
if (getConfiguration().getCompatibilityInstance()
.getStoreMapCollectionInEntityAsBlob())
return null;
@@ -916,6 +922,7 @@ public class MappingRepository
protected FieldStrategy handlerMapStrategy(FieldMapping field,
ValueHandler khandler, ValueHandler vhandler, boolean krel,
boolean vrel, boolean installHandlers) {
+ // TODO: JPA 2.0 should ignore this flag and not to serialize
if (getConfiguration().getCompatibilityInstance()
.getStoreMapCollectionInEntityAsBlob())
return null;
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java
index a239473d3..21861e450 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerCollectionTableFieldStrategy.java
@@ -97,10 +97,7 @@ public class HandlerCollectionTableFieldStrategy
throw new MetaDataException(_loc.get("not-coll", field));
assertNotMappedBy();
- // JPA2.0 allows schema for @CollectionTable(used with
- // @ElementCollection)
- if (!field.isElementCollection())
- field.getValueInfo().assertNoSchemaComponents(field, !adapt);
+ field.getValueInfo().assertNoSchemaComponents(field, !adapt);
field.getKeyMapping().getValueInfo().assertNoSchemaComponents
(field.getKey(), !adapt);
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java
index e7859a2c4..d64c4302a 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerHandlerMapTableFieldStrategy.java
@@ -108,10 +108,15 @@ public class HandlerHandlerMapTableFieldStrategy
field.mapJoin(adapt, true);
_kio = new ColumnIO();
- DBDictionary dict = field.getMappingRepository().getDBDictionary();
- _kcols = HandlerStrategies.map(key,
- dict.getValidColumnName("key", field.getTable()), _kio, adapt);
-
+ List columns = key.getValueInfo().getColumns();
+ if (columns != null && columns.size() > 0) {
+ // MapKeyColumn is used
+ _kcols = HandlerStrategies.map(key, "key", _kio, adapt);
+ } else {
+ DBDictionary dict = field.getMappingRepository().getDBDictionary();
+ _kcols = HandlerStrategies.map(key,
+ dict.getValidColumnName("key", field.getTable()), _kio, adapt);
+ }
_vio = new ColumnIO();
_vcols = HandlerStrategies.map(val, "value", _vio, adapt);
field.mapPrimaryKey(adapt);
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java
index a931b4c0c..5c9307bb6 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/HandlerRelationMapTableFieldStrategy.java
@@ -51,6 +51,10 @@ public class HandlerRelationMapTableFieldStrategy
return _kcols;
}
+ public ColumnIO getKeyColumnIO() {
+ return _kio;
+ }
+
public Column[] getValueColumns(ClassMapping cls) {
return field.getElementMapping().getColumns();
}
@@ -83,8 +87,11 @@ public class HandlerRelationMapTableFieldStrategy
sel.select(_kcols);
sel.whereForeignKey(field.getJoinForeignKey(),
sm.getObjectId(), field.getDefiningMapping(), store);
-
- Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
+ FieldMapping mapped = field.getMappedByMapping();
+ Joins joins = null;
+ if (mapped == null)
+ joins = joinValueRelation(sel.newJoins(), vals[idx]);
+
sel.select(vals[idx], field.getElementMapping().
getSelectSubclasses(), store, fetch, eagerMode, joins);
@@ -129,23 +136,28 @@ public class HandlerRelationMapTableFieldStrategy
ValueMapping val = field.getElementMapping();
if (val.getTypeCode() != JavaTypes.PC || val.isEmbeddedPC())
throw new MetaDataException(_loc.get("not-relation", val));
- assertNotMappedBy();
+ FieldMapping mapped = field.getMappedByMapping();
+
+ if (mapped != null) // map to the owner table
+ handleMappedBy(adapt);
+ else {
+ // map to a separate table
+ field.mapJoin(adapt, true);
+ if (val.getTypeMapping().isMapped()) {
+ ValueMappingInfo vinfo = val.getValueInfo();
+ ForeignKey fk = vinfo.getTypeJoin(val, "value", false, adapt);
+ val.setForeignKey(fk);
+ val.setColumnIO(vinfo.getColumnIO());
+ } else
+ RelationStrategies.mapRelationToUnmappedPC(val, "value", adapt);
- field.mapJoin(adapt, true);
+ val.mapConstraints("value", adapt);
+ }
_kio = new ColumnIO();
DBDictionary dict = field.getMappingRepository().getDBDictionary();
_kcols = HandlerStrategies.map(key,
dict.getValidColumnName("key", field.getTable()), _kio, adapt);
- if (val.getTypeMapping().isMapped()) {
- ValueMappingInfo vinfo = val.getValueInfo();
- ForeignKey fk = vinfo.getTypeJoin(val, "value", false, adapt);
- val.setForeignKey(fk);
- val.setColumnIO(vinfo.getColumnIO());
- } else
- RelationStrategies.mapRelationToUnmappedPC(val, "value", adapt);
-
- val.mapConstraints("value", adapt);
field.mapPrimaryKey(adapt);
}
@@ -164,6 +176,8 @@ public class HandlerRelationMapTableFieldStrategy
throws SQLException {
if (map == null || map.isEmpty())
return;
+ if (field.getMappedBy() != null)
+ return;
Row row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java
index 4a7598ebc..f1411167d 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/MapTableFieldStrategy.java
@@ -26,6 +26,7 @@ import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.FieldStrategy;
+import org.apache.openjpa.jdbc.meta.ValueMapping;
import org.apache.openjpa.jdbc.schema.ForeignKey;
import org.apache.openjpa.jdbc.sql.Joins;
import org.apache.openjpa.jdbc.sql.Result;
@@ -33,6 +34,7 @@ import org.apache.openjpa.jdbc.sql.Row;
import org.apache.openjpa.jdbc.sql.RowManager;
import org.apache.openjpa.jdbc.sql.Select;
import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.MetaDataException;
@@ -173,4 +175,78 @@ public abstract class MapTableFieldStrategy
protected ClassMapping[] getIndependentElementMappings(boolean traverse) {
return ClassMapping.EMPTY_MAPPINGS;
}
+
+ protected void handleMappedBy(boolean adapt){
+ boolean criteria = field.getValueInfo().getUseClassCriteria();
+ // check for named inverse
+ FieldMapping mapped = field.getMappedByMapping();
+ if (mapped != null) {
+ field.getMappingInfo().assertNoSchemaComponents(field, !adapt);
+ field.getValueInfo().assertNoSchemaComponents(field, !adapt);
+ mapped.resolve(mapped.MODE_META | mapped.MODE_MAPPING);
+
+ if (!mapped.isMapped() || mapped.isSerialized())
+ throw new MetaDataException(_loc.get("mapped-by-unmapped",
+ field, mapped));
+
+ if (mapped.getTypeCode() == JavaTypes.PC) {
+ if (mapped.getJoinDirection() == mapped.JOIN_FORWARD) {
+ field.setJoinDirection(field.JOIN_INVERSE);
+ field.setColumns(mapped.getDefiningMapping().
+ getPrimaryKeyColumns());
+ } else if (isTypeUnjoinedSubclass(mapped))
+ throw new MetaDataException(_loc.get
+ ("mapped-inverse-unjoined", field.getName(),
+ field.getDefiningMapping(), mapped));
+ ForeignKey fk = mapped.getForeignKey(field.getDefiningMapping());
+ field.setForeignKey(fk);
+ field.setJoinForeignKey(fk);
+ } else if (mapped.getElement().getTypeCode() == JavaTypes.PC) {
+ if (isTypeUnjoinedSubclass(mapped.getElementMapping()))
+ throw new MetaDataException(_loc.get
+ ("mapped-inverse-unjoined", field.getName(),
+ field.getDefiningMapping(), mapped));
+
+ // warn the user about making the collection side the owner
+ Log log = field.getRepository().getLog();
+ if (log.isInfoEnabled())
+ log.info(_loc.get("coll-owner", field, mapped));
+ ValueMapping elem = mapped.getElementMapping();
+ ForeignKey fk = elem.getForeignKey();
+ field.setForeignKey(fk);
+ field.setJoinForeignKey(fk);
+ } else
+ throw new MetaDataException(_loc.get("not-inv-relation",
+ field, mapped));
+
+ field.setUseClassCriteria(criteria);
+ return;
+ }
+/*
+ // this is necessary to support openjpa 3 mappings, which didn't
+ // differentiate between secondary table joins and relations built
+ // around an inverse key: check to see if we're mapped as a secondary
+ // table join but we're in the table of the related type, and if so
+ // switch our join mapping info to our value mapping info
+ String tableName = field.getMappingInfo().getTableName();
+ Table table = field.getTypeMapping().getTable();
+ ValueMappingInfo vinfo = field.getValueInfo();
+ if (tableName != null && table != null
+ && (tableName.equalsIgnoreCase(table.getName())
+ || tableName.equalsIgnoreCase(table.getFullName()))) {
+ vinfo.setJoinDirection(MappingInfo.JOIN_INVERSE);
+ vinfo.setColumns(field.getMappingInfo().getColumns());
+ field.getMappingInfo().setTableName(null);
+ field.getMappingInfo().setColumns(null);
+ }
+*/
+ }
+
+ protected boolean isTypeUnjoinedSubclass(ValueMapping mapped) {
+ ClassMapping def = field.getDefiningMapping();
+ for (; def != null; def = def.getJoinablePCSuperclassMapping())
+ if (def == mapped.getTypeMapping())
+ return false;
+ return true;
+ }
}
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
index c9098e45b..2c3eb143c 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
@@ -33,6 +34,7 @@ import org.apache.openjpa.jdbc.kernel.JDBCStoreManager;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.Embeddable;
import org.apache.openjpa.jdbc.meta.FieldMapping;
+import org.apache.openjpa.jdbc.meta.FieldStrategy;
import org.apache.openjpa.jdbc.meta.Joinable;
import org.apache.openjpa.jdbc.meta.MappingInfo;
import org.apache.openjpa.jdbc.meta.ValueMapping;
@@ -57,6 +59,7 @@ import org.apache.openjpa.kernel.OpenJPAStateManager;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.ImplHelper;
@@ -213,10 +216,67 @@ public class RelationFieldStrategy
updateInverse(sm, rel, store, rm);
else {
Row row = field.getRow(sm, store, rm, Row.ACTION_INSERT);
- if (row != null)
+ if (row != null) {
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);
+ }
}
}
+
+ private void setMapKey(OpenJPAStateManager sm, OpenJPAStateManager rel,
+ JDBCStore store, Row row) throws SQLException {
+ if (rel == null)
+ return;
+ ClassMetaData meta = rel.getMetaData();
+ FieldMapping[] fields = ((ClassMapping)meta).getFieldMappings();
+ for (int i = 0; i < fields.length; i++) {
+ FieldMetaData mappedBy = fields[i].getMappedByMetaData();
+ if (mappedBy == field) {
+ if (fields[i].getDeclaredTypeCode() == JavaTypes.MAP) {
+ Map mapObj = (Map)rel.fetchObjectField(
+ fields[i].getIndex());
+ Object keyObj = getMapKeyObj(mapObj,
+ sm.getPersistenceCapable());
+ ValueMapping key = fields[i].getKeyMapping();
+ if (!key.isEmbedded()) {
+ if (keyObj instanceof PersistenceCapable) {
+ OpenJPAStateManager keySm = RelationStrategies.
+ getStateManager(keyObj, store.getContext());
+ // key is an entity
+ ForeignKey fk = fields[i].getKeyMapping().
+ getForeignKey();
+ ColumnIO io = new ColumnIO();
+ row.setForeignKey(fk, io, keySm);
+ }
+ } else {
+ // key is an embeddable or basic type
+ FieldStrategy strategy = fields[i].getStrategy();
+ if (strategy instanceof
+ HandlerRelationMapTableFieldStrategy) {
+ HandlerRelationMapTableFieldStrategy strat =
+ (HandlerRelationMapTableFieldStrategy) strategy;
+ Column[] kcols = strat.getKeyColumns((ClassMapping)meta);
+ ColumnIO kio = strat.getKeyColumnIO();
+ HandlerStrategies.set(key, keyObj, store, row, kcols,
+ kio, true);
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private Object getMapKeyObj(Map mapObj, Object value) {
+ Set keySet = mapObj.keySet();
+ for (Object key : keySet) {
+ if (mapObj.get(key) == value)
+ return key;
+ }
+ return null;
+ }
public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java
index 60770b6cf..c4c96fe0d 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationRelationMapTableFieldStrategy.java
@@ -110,7 +110,10 @@ public class RelationRelationMapTableFieldStrategy
// order before select in case we're faking union with
// multiple selects; order vals used to merge results
- Joins joins = joinValueRelation(sel.newJoins(), vals[idx]);
+ FieldMapping mapped = field.getMappedByMapping();
+ Joins joins = null;
+ if (mapped == null)
+ joins = joinValueRelation(sel.newJoins(), vals[idx]);
sel.orderBy(field.getKeyMapping().getColumns(), true, true);
sel.select(vals[idx], field.getElementMapping().
getSelectSubclasses(), store, fetch, eagerMode, joins);
@@ -176,11 +179,14 @@ public class RelationRelationMapTableFieldStrategy
ValueMapping val = field.getElementMapping();
if (val.getTypeCode() != JavaTypes.PC || val.isEmbeddedPC())
throw new MetaDataException(_loc.get("not-relation", val));
- assertNotMappedBy();
-
- field.mapJoin(adapt, true);
+ FieldMapping mapped = field.getMappedByMapping();
+ if (mapped != null)
+ handleMappedBy(adapt);
+ else {
+ field.mapJoin(adapt, true);
+ mapTypeJoin(val, "value", adapt);
+ }
mapTypeJoin(key, "key", adapt);
- mapTypeJoin(val, "value", adapt);
field.mapPrimaryKey(adapt);
}
@@ -212,6 +218,9 @@ public class RelationRelationMapTableFieldStrategy
throws SQLException {
if (map == null || map.isEmpty())
return;
+
+ if (field.getMappedBy() != null)
+ return;
Row row = rm.getSecondaryRow(field.getTable(), Row.ACTION_INSERT);
row.setForeignKey(field.getJoinForeignKey(), field.getJoinColumnIO(),
diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaDataImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaDataImpl.java
index 51cfe2e2c..ff289c8e3 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaDataImpl.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaDataImpl.java
@@ -432,7 +432,11 @@ public class ValueMetaDataImpl
_owner.getDefiningMetaData().getEnvClassLoader(), false);
if (meta != null)
_decCode = JavaTypes.PC;
- if (!isEmbedded())
+
+ if (meta != null && meta.isEmbeddedOnly())
+ setEmbedded(true);
+
+ if (!isEmbedded())
_decTypeMeta = meta;
}
diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
index 867959a81..54a5d7192 100644
--- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
+++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
@@ -44,6 +44,9 @@ import javax.persistence.Inheritance;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.MapKeyJoinColumn;
+import javax.persistence.MapKeyJoinColumns;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.PrimaryKeyJoinColumns;
import javax.persistence.SecondaryTable;
@@ -141,6 +144,9 @@ public class AnnotationPersistenceMappingParser
_tags.put(KeyJoinColumns.class, KEY_JOIN_COLS);
_tags.put(KeyNonpolymorphic.class, KEY_NONPOLY);
_tags.put(KeyStrategy.class, KEY_STRAT);
+ _tags.put(MapKeyColumn.class, MAP_KEY_COL);
+ _tags.put(MapKeyJoinColumn.class, MAP_KEY_JOIN_COL);
+ _tags.put(MapKeyJoinColumns.class, MAP_KEY_JOIN_COLS);
_tags.put(PrimaryKeyJoinColumn.class, PK_JOIN_COL);
_tags.put(PrimaryKeyJoinColumns.class, PK_JOIN_COLS);
_tags.put(SecondaryTable.class, SECONDARY_TABLE);
@@ -1051,6 +1057,16 @@ public class AnnotationPersistenceMappingParser
fm.getKeyMapping().getValueInfo()
.setStrategy(((KeyStrategy) anno).value());
break;
+ case MAP_KEY_COL:
+ parseMapKeyColumn(fm, (MapKeyColumn) anno);
+ break;
+ case MAP_KEY_JOIN_COL:
+ parseMapKeyJoinColumns(fm, (MapKeyJoinColumn) anno);
+ break;
+ case MAP_KEY_JOIN_COLS:
+ parseMapKeyJoinColumns(fm,
+ ((MapKeyJoinColumns) anno).value());
+ break;
case PK_JOIN_COL:
parsePrimaryKeyJoinColumns(fm, (PrimaryKeyJoinColumn) anno);
break;
@@ -1699,4 +1715,89 @@ public class AnnotationPersistenceMappingParser
col.setFlag (Column.FLAG_UNUPDATABLE, !join.updatable ());
return col;
}
+
+ /**
+ * Parse @MapKeyColumn.
+ */
+ protected void parseMapKeyColumn(FieldMapping fm, MapKeyColumn anno) {
+ if (!fm.isElementCollection())
+ throw new UnsupportedException(_loc.get("unsupported", fm,
+ anno.toString()));
+
+ int unique = 0;
+ Column col = new Column();
+ setupMapKeyColumn(fm, col, anno);
+ unique |= (anno.unique()) ? TRUE : FALSE;
+ setMapKeyColumn(fm, fm.getKeyMapping().getValueInfo(), col, unique);
+ }
+
+ /**
+ * Setup the given column with information from the given annotation.
+ */
+ private static void setupMapKeyColumn(FieldMapping fm, Column col,
+ MapKeyColumn anno) {
+ if (!StringUtils.isEmpty(anno.name()))
+ col.setName(anno.name());
+ else
+ col.setName(fm.getName() + "_" + "KEY");
+ if (!StringUtils.isEmpty(anno.columnDefinition()))
+ col.setTypeName(anno.columnDefinition());
+ if (anno.precision() != 0)
+ col.setSize(anno.precision());
+ else if (anno.length() != 255)
+ col.setSize(anno.length());
+ col.setNotNull(!anno.nullable());
+ col.setDecimalDigits(anno.scale());
+ col.setFlag(Column.FLAG_UNINSERTABLE, !anno.insertable());
+ col.setFlag(Column.FLAG_UNUPDATABLE, !anno.updatable());
+ }
+
+ /**
+ * Set the given map key column as the map key column for fm
.
+ *
+ * @param unique bitwise combination of TRUE and FALSE for the
+ * unique attribute of the column
+ */
+ protected void setMapKeyColumn(FieldMapping fm, MappingInfo info,
+ Column col, int unique) {
+ List cols = new ArrayList();
+ cols.add(col);
+ info.setColumns(cols);
+ if (unique == TRUE)
+ info.setUnique(new org.apache.openjpa.jdbc.schema.Unique());
+ }
+
+ /**
+ * Parse @MapKeyJoinColumn(s).
+ */
+ private void parseMapKeyJoinColumns(FieldMapping fm, MapKeyJoinColumn... joins) {
+ if (joins.length == 0)
+ return;
+
+ List cols = new ArrayList(joins.length);
+ int unique = 0;
+ for (int i = 0; i < joins.length; i++) {
+ cols.add(newColumn(joins[i]));
+ unique |= (joins[i].unique()) ? TRUE : FALSE;
+ }
+ setColumns(fm, fm.getKeyMapping().getValueInfo(), cols, unique);
+ }
+
+ /**
+ * Create a new schema column with information from the given annotation.
+ */
+ private static Column newColumn(MapKeyJoinColumn join) {
+ Column col = new Column();
+ if (!StringUtils.isEmpty(join.name()))
+ col.setName(join.name());
+ if (!StringUtils.isEmpty(join.columnDefinition()))
+ col.setName(join.columnDefinition());
+ if (!StringUtils.isEmpty(join.referencedColumnName()))
+ col.setTarget(join.referencedColumnName());
+ col.setNotNull(!join.nullable());
+ col.setFlag(Column.FLAG_UNINSERTABLE, !join.insertable());
+ col.setFlag(Column.FLAG_UNUPDATABLE, !join.updatable ());
+ return col;
+ }
+
}
diff --git a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java
index c2d261969..ca208b7c7 100644
--- a/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java
+++ b/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/MappingTag.java
@@ -88,6 +88,9 @@ enum MappingTag {
KEY_JOIN_COLS,
KEY_NONPOLY,
KEY_STRAT,
+ MAP_KEY_COL,
+ MAP_KEY_JOIN_COL,
+ MAP_KEY_JOIN_COLS,
MAPPING_OVERRIDE,
MAPPING_OVERRIDES,
NONPOLY,
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Company1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Company1.java
new file mode 100644
index 000000000..c35c97bf8
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Company1.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.*;
+
+@Entity
+public class Company1 {
+ @Id
+ int id;
+
+ @OneToMany(targetEntity=VicePresident.class)
+ @MapKeyClass(Division.class)
+ Map organization = new HashMap();
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getOrganization() {
+ return organization;
+ }
+
+ public void addToOrganization(Division division, VicePresident vp) {
+ organization.put(division, vp);
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Company2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Company2.java
new file mode 100644
index 000000000..0aad92ec1
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Company2.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.*;
+
+@Entity
+public class Company2 {
+ @Id
+ int id;
+
+ @OneToMany
+ Map organization =
+ new HashMap();
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getOrganization() {
+ return organization;
+ }
+
+ public void addToOrganization(Division division, VicePresident vp) {
+ organization.put(division, vp);
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department1.java
new file mode 100644
index 000000000..342e3e906
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department1.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.*;
+
+@Entity
+public class Department1 {
+
+ int deptId;
+
+ Map empMap = new HashMap();
+
+ @Id
+ public int getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptId(int deptId) {
+ this.deptId = deptId;
+ }
+
+ @OneToMany(mappedBy="department", fetch=FetchType.EAGER)
+ @MapKey(name="empId")
+ public Map getEmpMap() {
+ return empMap;
+ }
+
+ public void setEmpMap(Map empMap) {
+ this.empMap = empMap;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department2.java
new file mode 100644
index 000000000..5fedab094
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department2.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.*;
+
+@Entity
+public class Department2 {
+
+ int deptId;
+ Map empMap = new HashMap();
+
+ @Id
+ public int getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptId(int deptId) {
+ this.deptId = deptId;
+ }
+
+ @OneToMany(mappedBy="department")
+ @MapKey(name="empPK")
+ public Map getEmpMap() {
+ return empMap;
+ }
+
+ public void setEmpMap(Map empMap) {
+ this.empMap = empMap;
+ }
+
+ public void addEmployee(Employee2 emp) {
+ empMap.put(emp.getEmpPK(), emp);
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department3.java
new file mode 100644
index 000000000..e76516188
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Department3.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.MapKey;
+import javax.persistence.OneToMany;
+
+@Entity
+public class Department3 {
+
+ @Id
+ int deptId;
+
+ @OneToMany(mappedBy="department", fetch=FetchType.EAGER)
+ @MapKey(name="name")
+ Map emps = new HashMap();
+
+ public int getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptId(int deptId) {
+ this.deptId = deptId;
+ }
+
+ public Map getEmployees() {
+ return emps;
+ }
+
+ public void addEmployee(Employee3 emp) {
+ emps.put(emp.getName(), emp);
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Division.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Division.java
new file mode 100644
index 000000000..64849c930
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Division.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class Division {
+ @Id
+ int id;
+
+ String name;
+
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee1.java
new file mode 100644
index 000000000..00d6f1189
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee1.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import javax.persistence.*;
+
+@Entity
+public class Employee1 {
+ @Id
+ int empId;
+
+ @ManyToOne
+ @JoinColumn(name="dept_id")
+ Department1 department;
+
+ public int getEmpId() {
+ return empId;
+ }
+
+ public void setEmpId(int empId) {
+ this.empId = empId;
+ }
+
+ public Department1 getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(Department1 department) {
+ this.department = department;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee2.java
new file mode 100644
index 000000000..2b014d229
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee2.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.Date;
+
+import javax.persistence.*;
+
+@Entity
+public class Employee2 {
+ EmployeePK2 empPK;
+
+ Department2 department;
+
+ public Employee2() {}
+
+ public Employee2(String name, Date bDate) {
+ this.empPK = new EmployeePK2(name, bDate);
+ }
+
+ @EmbeddedId
+ public EmployeePK2 getEmpPK() {
+ return empPK;
+ }
+
+ public void setEmpPK(EmployeePK2 empPK) {
+ this.empPK = empPK;
+ }
+
+ @ManyToOne
+ @JoinColumn(name="dept_id")
+ public Department2 getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(Department2 department) {
+ this.department = department;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee3.java
new file mode 100644
index 000000000..f57b261e1
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Employee3.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import javax.persistence.*;
+
+@Entity
+public class Employee3 {
+ @Id
+ int empId;
+
+ @ManyToOne
+ @JoinColumn(name="dept_id")
+ Department3 department;
+
+ @Embedded
+ EmployeeName3 name;
+
+ public int getEmpId() {
+ return empId;
+ }
+
+ public void setEmpId(int empId) {
+ this.empId = empId;
+ }
+
+ public Department3 getDepartment() {
+ return department;
+ }
+
+ public void setDepartment(Department3 department) {
+ this.department = department;
+ }
+
+ public EmployeeName3 getName() {
+ return name;
+ }
+
+ public void setName(EmployeeName3 name) {
+ this.name = name;
+ }
+
+
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/EmployeeName3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/EmployeeName3.java
new file mode 100644
index 000000000..1fb091795
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/EmployeeName3.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class EmployeeName3 {
+
+ String fName;
+ String lName;
+
+ public EmployeeName3() {}
+
+ public EmployeeName3(String fName, String lName) {
+ this.fName = fName;
+ this.lName = lName;
+ }
+
+ public String getFName() {
+ return fName;
+ }
+
+ public void setFName(String fName) {
+ this.fName = fName;
+ }
+
+ public String getLName() {
+ return lName;
+ }
+
+ public void setLName(String lName) {
+ this.lName = lName;
+ }
+
+ public boolean equals(Object o) {
+ if (!(o instanceof EmployeeName3)) return false;
+ EmployeeName3 other = (EmployeeName3) o;
+ if (fName.equals(other.fName) &&
+ lName.equals(other.lName))
+ return true;
+ return false;
+ }
+
+ public int hashCode() {
+ int ret = 0;
+ ret += lName.hashCode();
+ ret = 31 * ret + fName.hashCode();
+ return ret;
+ }
+
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/EmployeePK2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/EmployeePK2.java
new file mode 100644
index 000000000..5faef1e4f
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/EmployeePK2.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.*;
+
+@Embeddable
+public class EmployeePK2 implements Serializable {
+ String name;
+ Date bDay;
+
+ public EmployeePK2() {}
+ public EmployeePK2(String name, Date bDay) {
+ this.name = name;
+ this.bDay = bDay;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof EmployeePK2)) return false;
+ EmployeePK2 pk = (EmployeePK2) o;
+ if (pk.name.equals(name) &&
+ pk.bDay.equals(bDay)) return true;
+ return false;
+ }
+
+ public int hashCode() {
+ int code = 0;
+ code = code * 31 + name.hashCode();
+ code = code * 31 + bDay.hashCode();
+ return code;
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item1.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item1.java
new file mode 100644
index 000000000..68768fb84
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item1.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.*;
+
+@Entity
+public class Item1 {
+ @Id
+ int id;
+
+ @ElementCollection(targetClass=String.class)
+ @MapKeyClass(String.class)
+ Map images = new HashMap();
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getImages() {
+ return images;
+ }
+
+ public void addImage(String imageName, String fileName) {
+ images.put(imageName, fileName);
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item2.java
new file mode 100644
index 000000000..2f39bbabb
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item2.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.*;
+
+@Entity
+public class Item2 {
+ @Id
+ int id;
+
+ @ElementCollection
+ Map images = new HashMap();
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getImages() {
+ return images;
+ }
+
+ public void addImage(String imageName, String fileName) {
+ images.put(imageName, fileName);
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item3.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item3.java
new file mode 100644
index 000000000..b23b41205
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/Item3.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.*;
+
+@Entity
+public class Item3 {
+ @Id
+ int id;
+
+ @ElementCollection
+ @MapKeyColumn(name="IMAGE_NAME")
+ @Column(name="IMAGE_FILENAME")
+ @CollectionTable(name="IMAGE_MAPPING")
+ Map images = new HashMap();
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public Map getImages() {
+ return images;
+ }
+
+ public void addImage(String imageName, String fileName) {
+ images.put(imageName, fileName);
+ }
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java
index c4042a4c3..cd0efbade 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/TestEmbeddable.java
@@ -19,6 +19,7 @@
package org.apache.openjpa.persistence.embed;
import java.util.Collection;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -29,30 +30,38 @@ import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
-
+import junit.framework.Assert;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
-
public class TestEmbeddable extends SingleEMFTestCase {
public int numEmbeddables = 1;
public int numBasicTypes = 1;
- public int ID = 1;
public int numProgramManagers = 2;
public int numNickNames = 3;
-
public int numEmployeesPerPhoneNumber = 1;
public int numPhoneNumbersPerEmployee = 2;
public int numEmployeesPerProgramManager = 2;
public int numEmployees = numProgramManagers * numEmployeesPerProgramManager;
public int numPhoneNumbers = numEmployees * numPhoneNumbersPerEmployee;
-
- public Map phones = new HashMap();
- public Map employees = new HashMap();
+ public int numDepartments = 2;
+ public int numEmployeesPerDept = 2;
+ public int numItems = 2;
+ public int numImagesPerItem = 3;
+ public int numCompany = 2;
+ public int numDivisionsPerCo = 2;
+ public int ID = 1;
+ public int itemId = 1;
+ public int compId = 1;
+ public int divId = 1;
+ public int vpId = 1;
+ public int deptId = 1;
public int empId = 1;
public int phoneId = 1;
public int pmId = 1;
public int parkingSpotId = 1;
+ public Map phones = new HashMap();
+ public Map employees = new HashMap();
public void setUp() {
setUp(Embed.class, Embed_Coll_Embed.class, Embed_Coll_Integer.class,
@@ -65,7 +74,12 @@ public class TestEmbeddable extends SingleEMFTestCase {
EntityA_Coll_Embed_Embed.class, ContactInfo.class,
Employee.class, JobInfo.class, LocationDetails.class,
ParkingSpot.class, PhoneNumber.class, ProgramManager.class,
- CLEAR_TABLES);
+ Department1.class, Employee1.class, Department2.class,
+ Employee2.class, EmployeePK2.class, Department3.class,
+ Employee3.class, EmployeeName3.class, Item1.class, Item2.class,
+ Item3.class, Company1.class, Company2.class, Division.class,
+ VicePresident.class,
+ DROP_TABLES);
}
public void testEntityA_Coll_String() {
@@ -128,6 +142,18 @@ public class TestEmbeddable extends SingleEMFTestCase {
findEmployeeObj();
}
+ public void testMapKey() {
+ createObjMapKey();
+ queryObjMapKey();
+ findObjMapKey();
+ }
+
+ public void testMapKeyClass() {
+ createObjMapKeyClass();
+ queryObjMapKeyClass();
+ findObjMapKeyClass();
+ }
+
/*
* Create EntityA_Coll_String
*/
@@ -528,7 +554,7 @@ public class TestEmbeddable extends SingleEMFTestCase {
public void queryEmployeeObj() {
queryProgramManager(emf);
- queryEmployee(emf);
+ queryEmployeeObj(emf);
queryPhoneNumber(emf);
queryParkingSpot(emf);
}
@@ -572,7 +598,7 @@ public class TestEmbeddable extends SingleEMFTestCase {
em.close();
}
- public void queryEmployee(EntityManagerFactory emf) {
+ public void queryEmployeeObj(EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
EntityTransaction tran = em.getTransaction();
tran.begin();
@@ -1068,4 +1094,441 @@ public class TestEmbeddable extends SingleEMFTestCase {
tran.commit();
em.close();
}
+
+ public void createObjMapKey() {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ for (int i = 0; i < numDepartments; i++)
+ createDepartment1(em, deptId++);
+ for (int i = 0; i < numDepartments; i++)
+ createDepartment2(em, deptId++);
+ for (int i = 0; i < numDepartments; i++)
+ createDepartment3(em, deptId++);
+ tran.begin();
+ em.flush();
+ tran.commit();
+ em.close();
+ }
+
+ public void createObjMapKeyClass() {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ for (int i = 0; i < numItems; i++)
+ createItem1(em, itemId++);
+ for (int i = 0; i < numItems; i++)
+ createItem2(em, itemId++);
+ for (int i = 0; i < numItems; i++)
+ createItem3(em, itemId++);
+ for (int i = 0; i < numCompany; i++)
+ createCompany1(em, compId++);
+ for (int i = 0; i < numCompany; i++)
+ createCompany2(em, compId++);
+ tran.begin();
+ em.flush();
+ tran.commit();
+ em.close();
+ }
+
+ public void createItem1(EntityManager em, int id) {
+ Item1 item = new Item1();
+ item.setId(id);
+ for (int i = 0; i < numImagesPerItem; i++) {
+ item.addImage("image" + id + i, "file" + id + i);
+ }
+ em.persist(item);
+ }
+
+ public void createItem2(EntityManager em, int id) {
+ Item2 item = new Item2();
+ item.setId(id);
+ for (int i = 0; i < numImagesPerItem; i++) {
+ item.addImage("image" + id + i, "file" + id + i);
+ }
+ em.persist(item);
+ }
+
+ public void createItem3(EntityManager em, int id) {
+ System.out.println("In CreateItem3, id = " + id);
+ Item3 item = new Item3();
+ item.setId(id);
+ for (int i = 0; i < numImagesPerItem; i++) {
+ item.addImage("image" + id + i, "file" + id + i);
+ }
+ em.persist(item);
+ }
+
+ public void createCompany1(EntityManager em, int id) {
+ Company1 c = new Company1();
+ c.setId(id);
+ for (int i = 0; i < numDivisionsPerCo; i++) {
+ Division d = createDivision(em, divId++);
+ VicePresident vp = createVicePresident(em, vpId++);
+ c.addToOrganization(d, vp);
+ em.persist(d);
+ em.persist(vp);
+ }
+ em.persist(c);
+ }
+
+ public void createCompany2(EntityManager em, int id) {
+ Company2 c = new Company2();
+ c.setId(id);
+ for (int i = 0; i < numDivisionsPerCo; i++) {
+ Division d = createDivision(em, divId++);
+ VicePresident vp = createVicePresident(em, vpId++);
+ c.addToOrganization(d, vp);
+ em.persist(d);
+ em.persist(vp);
+ }
+ em.persist(c);
+ }
+
+ public Division createDivision(EntityManager em, int id) {
+ Division d = new Division();
+ d.setId(id);
+ d.setName("d" + id);
+ return d;
+ }
+
+ public VicePresident createVicePresident(EntityManager em, int id) {
+ VicePresident vp = new VicePresident();
+ vp.setId(id);
+ vp.setName("vp" + id);
+ return vp;
+ }
+
+ public void createDepartment1(EntityManager em, int id) {
+ Department1 d = new Department1();
+ d.setDeptId(id);
+ Map emps = new HashMap();
+ for (int i = 0; i < numEmployeesPerDept; i++) {
+ Employee1 e = createEmployee1(em, empId++);
+ //d.addEmployee1(e);
+ emps.put(e.getEmpId(), e);
+ e.setDepartment(d);
+ em.persist(e);
+ }
+ d.setEmpMap(emps);
+ em.persist(d);
+ }
+
+ public Employee1 createEmployee1(EntityManager em, int id) {
+ Employee1 e = new Employee1();
+ e.setEmpId(id);
+ return e;
+ }
+
+ public void createDepartment2(EntityManager em, int id) {
+ Department2 d = new Department2();
+ d.setDeptId(id);
+ for (int i = 0; i < numEmployeesPerDept; i++) {
+ Employee2 e = createEmployee2(em, empId++);
+ d.addEmployee(e);
+ e.setDepartment(d);
+ em.persist(e);
+ }
+ em.persist(d);
+ }
+
+ public Employee2 createEmployee2(EntityManager em, int id) {
+ Employee2 e = new Employee2("e" + id, new Date());
+ return e;
+ }
+
+ public void createDepartment3(EntityManager em, int id) {
+ Department3 d = new Department3();
+ d.setDeptId(id);
+ for (int i = 0; i < numEmployeesPerDept; i++) {
+ Employee3 e = createEmployee3(em, empId++);
+ d.addEmployee(e);
+ e.setDepartment(d);
+ em.persist(e);
+ }
+ em.persist(d);
+ }
+
+ public Employee3 createEmployee3(EntityManager em, int id) {
+ Employee3 e = new Employee3();
+ EmployeeName3 name = new EmployeeName3("f" + id, "l" + id);
+ e.setEmpId(id);
+ e.setName(name);
+ return e;
+ }
+
+ public void findObjMapKey() {
+ EntityManager em = emf.createEntityManager();
+ Department1 d1 = em.find(Department1.class, 1);
+ assertDepartment1(d1);
+
+ Employee1 e1 = em.find(Employee1.class, 1);
+ assertEmployee1(e1);
+
+ Department2 d2 = em.find(Department2.class, 3);
+ assertDepartment2(d2);
+
+ Map emps = d2.getEmpMap();
+ Set keys = emps.keySet();
+ for (EmployeePK2 key : keys) {
+ Employee2 e2 = em.find(Employee2.class, key);
+ assertEmployee2(e2);
+ }
+
+ Department3 d3 = em.find(Department3.class, 5);
+ assertDepartment3(d3);
+
+ Employee3 e3 = em.find(Employee3.class, 9);
+ assertEmployee3(e3);
+
+ em.close();
+ }
+
+ public void assertDepartment1(Department1 d) {
+ int id = d.getDeptId();
+ Map es = d.getEmpMap();
+ Assert.assertEquals(2,es.size());
+ Set keys = es.keySet();
+ for (Object obj : keys) {
+ Integer empId = (Integer) obj;
+ Employee1 e = es.get(empId);
+ Assert.assertEquals(empId.intValue(), e.getEmpId());
+ }
+ }
+
+ public void assertDepartment2(Department2 d) {
+ int id = d.getDeptId();
+ Map es = d.getEmpMap();
+ Assert.assertEquals(2,es.size());
+ Set keys = es.keySet();
+ for (EmployeePK2 pk : keys) {
+ Employee2 e = es.get(pk);
+ Assert.assertEquals(pk, e.getEmpPK());
+ }
+ }
+
+ public void assertDepartment3(Department3 d) {
+ int id = d.getDeptId();
+ Map es = d.getEmployees();
+ Assert.assertEquals(2,es.size());
+ Set keys = es.keySet();
+ for (EmployeeName3 key : keys) {
+ Employee3 e = es.get(key);
+ Assert.assertEquals(key, e.getName());
+ }
+ }
+
+ public void assertEmployee1(Employee1 e) {
+ int id = e.getEmpId();
+ Department1 d = e.getDepartment();
+ assertDepartment1(d);
+ }
+
+ public void assertEmployee2(Employee2 e) {
+ EmployeePK2 pk = e.getEmpPK();
+ Department2 d = e.getDepartment();
+ assertDepartment2(d);
+ }
+
+ public void assertEmployee3(Employee3 e) {
+ int id = e.getEmpId();
+ Department3 d = e.getDepartment();
+ assertDepartment3(d);
+ }
+
+ public void queryObjMapKey() {
+ queryDepartment(emf);
+ queryEmployee(emf);
+ }
+
+ public void queryDepartment(EntityManagerFactory emf) {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ tran.begin();
+ Query q1 = em.createQuery("select d from Department1 d");
+ List ds1 = q1.getResultList();
+ for (Department1 d : ds1){
+ assertDepartment1(d);
+ }
+
+ Query q2 = em.createQuery("select d from Department2 d");
+ List ds2 = q2.getResultList();
+ for (Department2 d : ds2){
+ assertDepartment2(d);
+ }
+
+ Query q3 = em.createQuery("select d from Department3 d");
+ List ds3 = q3.getResultList();
+ for (Department3 d : ds3){
+ assertDepartment3(d);
+ }
+
+ tran.commit();
+ em.close();
+ }
+
+ public void queryEmployee(EntityManagerFactory emf) {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ tran.begin();
+ Query q1 = em.createQuery("select e from Employee1 e");
+ List es1 = q1.getResultList();
+ for (Employee1 e : es1){
+ assertEmployee1(e);
+ }
+
+ Query q2 = em.createQuery("select e from Employee2 e");
+ List es2 = q2.getResultList();
+ for (Employee2 e : es2){
+ assertEmployee2(e);
+ }
+
+ Query q3 = em.createQuery("select e from Employee3 e");
+ List es3 = q3.getResultList();
+ for (Employee3 e : es3){
+ assertEmployee3(e);
+ }
+ tran.commit();
+ em.close();
+ }
+
+ public void findObjMapKeyClass() {
+ EntityManager em = emf.createEntityManager();
+
+ Item1 item1 = em.find(Item1.class, 1);
+ assertItem1(item1);
+
+ Item2 item2 = em.find(Item2.class, 3);
+ assertItem2(item2);
+
+ Item3 item3 = em.find(Item3.class, 5);
+ assertItem3(item3);
+
+ Company1 c1 = em.find(Company1.class, 1);
+ assertCompany1(c1);
+
+ Company2 c2 = em.find(Company2.class, 3);
+ assertCompany2(c2);
+
+ Division d = em.find(Division.class, 1);
+ assertDivision(d);
+
+ VicePresident vp = em.find(VicePresident.class, 1);
+ assertVicePresident(vp);
+ }
+
+ public void assertItem1(Item1 item) {
+ int id = item.getId();
+ Map images = item.getImages();
+ Assert.assertEquals(numImagesPerItem, images.size());
+ }
+
+ public void assertItem2(Item2 item) {
+ int id = item.getId();
+ Map images = item.getImages();
+ Assert.assertEquals(numImagesPerItem, images.size());
+ }
+
+ public void assertItem3(Item3 item) {
+ int id = item.getId();
+ Map images = item.getImages();
+ Assert.assertEquals(numImagesPerItem, images.size());
+ }
+
+ public void assertCompany1(Company1 c) {
+ int id = c.getId();
+ Map organization = c.getOrganization();
+ Assert.assertEquals(2,organization.size());
+ }
+
+ public void assertCompany2(Company2 c) {
+ int id = c.getId();
+ Map organization = c.getOrganization();
+ Assert.assertEquals(2,organization.size());
+ }
+
+ public void assertDivision(Division d) {
+ int id = d.getId();
+ String name = d.getName();
+ }
+
+ public void assertVicePresident(VicePresident vp) {
+ int id = vp.getId();
+ String name = vp.getName();
+ }
+
+ public void queryObjMapKeyClass() {
+ queryItem(emf);
+ queryCompany(emf);
+ queryDivision(emf);
+ queryVicePresident(emf);
+ }
+
+ public void queryItem(EntityManagerFactory emf) {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ tran.begin();
+ Query q1 = em.createQuery("select i from Item1 i");
+ List is1 = q1.getResultList();
+ for (Item1 item : is1){
+ assertItem1(item);
+ }
+
+ Query q2 = em.createQuery("select i from Item2 i");
+ List is2 = q2.getResultList();
+ for (Item2 item : is2){
+ assertItem2(item);
+ }
+
+ Query q3 = em.createQuery("select i from Item3 i");
+ List is3 = q3.getResultList();
+ for (Item3 item : is3){
+ assertItem3(item);
+ }
+
+ tran.commit();
+ em.close();
+ }
+
+ public void queryCompany(EntityManagerFactory emf) {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ tran.begin();
+ Query q1 = em.createQuery("select c from Company1 c");
+ List cs1 = q1.getResultList();
+ for (Company1 c : cs1){
+ assertCompany1(c);
+ }
+ Query q2 = em.createQuery("select c from Company2 c");
+ List cs2 = q2.getResultList();
+ for (Company2 c : cs2){
+ assertCompany2(c);
+ }
+ tran.commit();
+ em.close();
+ }
+
+ public void queryDivision(EntityManagerFactory emf) {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ tran.begin();
+ Query q = em.createQuery("select d from Division d");
+ List ds = q.getResultList();
+ for (Division d : ds){
+ assertDivision(d);
+ }
+ tran.commit();
+ em.close();
+ }
+
+ public void queryVicePresident(EntityManagerFactory emf) {
+ EntityManager em = emf.createEntityManager();
+ EntityTransaction tran = em.getTransaction();
+ tran.begin();
+ Query q = em.createQuery("select vp from VicePresident vp");
+ List vps = q.getResultList();
+ for (VicePresident vp : vps){
+ assertVicePresident(vp);
+ }
+ tran.commit();
+ em.close();
+ }
}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/VicePresident.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/VicePresident.java
new file mode 100644
index 000000000..692c2e5ab
--- /dev/null
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/embed/VicePresident.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.embed;
+
+import javax.persistence.*;
+
+@Entity
+public class VicePresident {
+ @Id
+ int id;
+
+ String name;
+
+ @ManyToOne
+ Company1 co;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Company1 getCompany() {
+ return co;
+ }
+
+ public void setCompany(Company1 co) {
+ this.co = co;
+ }
+
+
+}
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestEmbeddableSuperclass.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestEmbeddableSuperclass.java
index 1f3adc11b..4f13c939e 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestEmbeddableSuperclass.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/annotations/TestEmbeddableSuperclass.java
@@ -24,6 +24,7 @@ import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.strats.ClobValueHandler;
+import org.apache.openjpa.jdbc.meta.strats.EmbedFieldStrategy;
import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy;
import org.apache.openjpa.jdbc.meta.strats.MaxEmbeddedClobFieldStrategy;
import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
@@ -106,7 +107,7 @@ public class TestEmbeddableSuperclass
assertTrue(fm.getStrategy() instanceof RelationFieldStrategy);
fm = cls.getFieldMapping("sup");
- assertTrue(fm.getStrategy() instanceof RelationFieldStrategy);
+ assertTrue(fm.getStrategy() instanceof EmbedFieldStrategy);
}
public void testPersistAndFind() {
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
index 02adf96ac..f54d491da 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/AnnotationPersistenceMetaDataParser.java
@@ -59,6 +59,7 @@ import javax.persistence.Lob;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.MapKey;
+import javax.persistence.MapKeyClass;
import javax.persistence.MappedSuperclass;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
@@ -143,6 +144,7 @@ public class AnnotationPersistenceMetaDataParser
_tags.put(Id.class, ID);
_tags.put(IdClass.class, ID_CLASS);
_tags.put(MapKey.class, MAP_KEY);
+ _tags.put(MapKeyClass.class, MAP_KEY_CLASS);
_tags.put(NamedNativeQueries.class, NATIVE_QUERIES);
_tags.put(NamedNativeQuery.class, NATIVE_QUERY);
_tags.put(NamedQueries.class, QUERIES);
@@ -1064,6 +1066,10 @@ public class AnnotationPersistenceMetaDataParser
if (isMappingOverrideMode())
parseMapKey(fmd, (MapKey) anno);
break;
+ case MAP_KEY_CLASS:
+ if (isMappingOverrideMode())
+ parseMapKeyClass(fmd, (MapKeyClass) anno);
+ break;
case ORDER_BY:
parseOrderBy(fmd,
(OrderBy) el.getAnnotation(OrderBy.class));
@@ -1399,6 +1405,17 @@ public class AnnotationPersistenceMetaDataParser
fmd.getKey().setValueMappedBy(name);
}
+ /**
+ * Parse @MapKeyClass.
+ */
+ private void parseMapKeyClass(FieldMetaData fmd, MapKeyClass anno) {
+ if (anno.value() != void.class)
+ fmd.getKey().setDeclaredType(anno.value());
+ else
+ throw new IllegalArgumentException(
+ "The value of the MapClassClass cannot be null");
+ }
+
/**
* Setup the field as a LOB mapping.
*/
@@ -1480,6 +1497,8 @@ public class AnnotationPersistenceMetaDataParser
*/
private void parseElementCollection(FieldMetaData fmd,
ElementCollection anno) {
+ // TODO: throw exception if the runtime env is OpenJpa 1.x
+
if (fmd.getDeclaredTypeCode() != JavaTypes.COLLECTION &&
fmd.getDeclaredTypeCode() != JavaTypes.MAP)
throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
index ed06ea6e2..a91fdb0aa 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataTag.java
@@ -44,6 +44,7 @@ public enum MetaDataTag {
ID_CLASS,
LOB,
MAP_KEY,
+ MAP_KEY_CLASS,
NATIVE_QUERIES,
NATIVE_QUERY,
QUERY_STRING,