OPENJPA-851: enhanced map support for JPA 2.0 (Spec 10.1.26,

10.1.27, 10.1.28, 10.1.29, 10.1.30, 2.7)

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@734319 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-01-14 04:11:32 +00:00
parent b8ec28b38a
commit c99c9d24f9
30 changed files with 1606 additions and 39 deletions

View File

@ -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();
}

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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(),

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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(),

View File

@ -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;
}

View File

@ -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 <code>fm</code>.
*
* @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<Column> cols = new ArrayList<Column>(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;
}
}

View File

@ -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,

View File

@ -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);
}
}

View File

@ -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<Division, VicePresident> organization =
new HashMap<Division, VicePresident>();
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);
}
}

View File

@ -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<Integer, Employee1> empMap = new HashMap<Integer, Employee1>();
@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<Integer, Employee1> getEmpMap() {
return empMap;
}
public void setEmpMap(Map<Integer, Employee1> empMap) {
this.empMap = empMap;
}
}

View File

@ -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<EmployeePK2, Employee2> empMap = new HashMap<EmployeePK2, Employee2>();
@Id
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
@OneToMany(mappedBy="department")
@MapKey(name="empPK")
public Map<EmployeePK2, Employee2> getEmpMap() {
return empMap;
}
public void setEmpMap(Map<EmployeePK2, Employee2> empMap) {
this.empMap = empMap;
}
public void addEmployee(Employee2 emp) {
empMap.put(emp.getEmpPK(), emp);
}
}

View File

@ -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<EmployeeName3, Employee3> emps = new HashMap<EmployeeName3, Employee3>();
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
public Map<EmployeeName3, Employee3> getEmployees() {
return emps;
}
public void addEmployee(Employee3 emp) {
emps.put(emp.getName(), emp);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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<String, String> getImages() {
return images;
}
public void addImage(String imageName, String fileName) {
images.put(imageName, fileName);
}
}

View File

@ -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<String, String> images = new HashMap<String, String>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Map<String, String> getImages() {
return images;
}
public void addImage(String imageName, String fileName) {
images.put(imageName, fileName);
}
}

View File

@ -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<String, String> images = new HashMap<String, String>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Map<String, String> getImages() {
return images;
}
public void addImage(String imageName, String fileName) {
images.put(imageName, fileName);
}
}

View File

@ -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<Integer, PhoneNumber> phones = new HashMap<Integer, PhoneNumber>();
public Map<Integer, Employee> employees = new HashMap<Integer, Employee>();
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<Integer, PhoneNumber> phones = new HashMap<Integer, PhoneNumber>();
public Map<Integer, Employee> employees = new HashMap<Integer, Employee>();
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<EmployeePK2> 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<Integer, Employee1> 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<EmployeePK2, Employee2> es = d.getEmpMap();
Assert.assertEquals(2,es.size());
Set<EmployeePK2> 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<EmployeeName3, Employee3> es = d.getEmployees();
Assert.assertEquals(2,es.size());
Set<EmployeeName3> 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<Department1> ds1 = q1.getResultList();
for (Department1 d : ds1){
assertDepartment1(d);
}
Query q2 = em.createQuery("select d from Department2 d");
List<Department2> ds2 = q2.getResultList();
for (Department2 d : ds2){
assertDepartment2(d);
}
Query q3 = em.createQuery("select d from Department3 d");
List<Department3> 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<Employee1> es1 = q1.getResultList();
for (Employee1 e : es1){
assertEmployee1(e);
}
Query q2 = em.createQuery("select e from Employee2 e");
List<Employee2> es2 = q2.getResultList();
for (Employee2 e : es2){
assertEmployee2(e);
}
Query q3 = em.createQuery("select e from Employee3 e");
List<Employee3> 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<Item1> is1 = q1.getResultList();
for (Item1 item : is1){
assertItem1(item);
}
Query q2 = em.createQuery("select i from Item2 i");
List<Item2> is2 = q2.getResultList();
for (Item2 item : is2){
assertItem2(item);
}
Query q3 = em.createQuery("select i from Item3 i");
List<Item3> 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<Company1> cs1 = q1.getResultList();
for (Company1 c : cs1){
assertCompany1(c);
}
Query q2 = em.createQuery("select c from Company2 c");
List<Company2> 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<Division> 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<VicePresident> vps = q.getResultList();
for (VicePresident vp : vps){
assertVicePresident(vp);
}
tran.commit();
em.close();
}
}

View File

@ -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;
}
}

View File

@ -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() {

View File

@ -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,

View File

@ -44,6 +44,7 @@ public enum MetaDataTag {
ID_CLASS,
LOB,
MAP_KEY,
MAP_KEY_CLASS,
NATIVE_QUERIES,
NATIVE_QUERY,
QUERY_STRING,